summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/elf/src
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/elf/src')
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c47
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c773
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c575
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c79
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c591
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c435
-rw-r--r--drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c6
7 files changed, 2506 insertions, 0 deletions
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c
new file mode 100644
index 00000000000..2e0f5928ffd
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+#include <cm/engine/elf/inc/common.h>
+#include <cm/engine/elf/inc/elfabi.h>
+
+#include <cm/engine/utils/inc/swap.h>
+#include <cm/engine/trace/inc/trace.h>
+
+typedef Elf64_Half ElfXX_Half;
+typedef Elf64_Word ElfXX_Word;
+typedef Elf64_Addr ElfXX_Addr;
+typedef Elf64_Off ElfXX_Off;
+
+typedef Elf64_Xword ElfXX_Xword;
+
+typedef Elf64_Ehdr ElfXX_Ehdr;
+typedef Elf64_Shdr ElfXX_Shdr;
+typedef Elf64_Sym ElfXX_Sym;
+typedef Elf64_Rela ElfXX_Rela;
+
+#undef ELFXX_R_SYM
+#define ELFXX_R_SYM ELF64_R_SYM
+#undef ELFXX_R_TYPE
+#define ELFXX_R_TYPE ELF64_R_TYPE
+#undef ELFXX_R_INFO
+#define ELFXX_R_INFO ELF64_R_INFO
+
+// TODO Here we assume big endian (MMDSP !)
+static Elf64_Half swapHalf(Elf64_Half half)
+{
+ return (Elf64_Half)swap16(half);
+}
+
+static Elf64_Word swapWord(Elf64_Word word)
+{
+ return (Elf64_Word)swap32(word);
+}
+
+static Elf64_Xword swapXword(Elf64_Xword xword)
+{
+ return (Elf64_Xword)swap64(xword);
+}
+
+#include "elfxx.c"
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c
new file mode 100644
index 00000000000..466d04508d1
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+/*
+ *
+ */
+#include <cm/engine/elf/inc/elfapi.h>
+#include <cm/engine/elf/inc/mpcal.h>
+#include <cm/inc/cm_def.h>
+
+//#include <cm/engine/component/inc/introspection.h>
+
+#include <cm/engine/utils/inc/mem.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/utils/inc/swap.h>
+#include <cm/engine/utils/inc/string.h>
+
+static void* getElfHeaderReference(t_tmp_elfdescription *elftmp, void* hdrref)
+{
+ if(hdrref != NULL)
+ return (void*)((int)swap32((t_uint32)hdrref) + (int)elftmp->elfheader);
+ else
+ return NULL;
+}
+
+static t_dup_char copyElfString(t_tmp_elfdescription *elftmp, char* idx)
+{
+ return cm_StringDuplicate((char*)getElfHeaderReference(elftmp, (void*)idx));
+}
+
+static t_cm_error getMemoryOffset(
+ t_elfdescription *elfhandle,
+ t_tmp_elfdescription *elftmp,
+ t_memory_purpose purpose,
+ const t_uint32 *addressInNmf,
+ t_memory_reference *memory) {
+
+ if(elftmp->isExecutable) {
+ return cm_ELF_GetMemory(elfhandle, elftmp,
+ swap32(*addressInNmf),
+ purpose,
+ memory);
+ } else {
+ return ELF64_getRelocationMemory(elfhandle, elftmp,
+ (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader,
+ memory);
+ }
+}
+
+static t_cm_error getAdressForExecutableOffsetElsewhere(
+ t_elfdescription *elfhandle,
+ t_tmp_elfdescription *elftmp,
+ const t_uint32 *addressInNmf,
+ t_memory_reference *memory) {
+ t_uint32 address;
+
+ address = swap32(*addressInNmf);
+ if(address == 0xFFFFFFFF)
+ {
+ memory->offset = 0x0;
+ memory->memory = NULL;
+ return CM_OK;
+ }
+
+ if(elftmp->isExecutable)
+ {
+ memory->offset = address;
+ memory->memory = NULL;
+ return CM_OK;
+ }
+
+ // Error log in elfhandle by previous call will be check in loadTemplate
+ return ELF64_getRelocationMemory(elfhandle, elftmp,
+ (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader,
+ memory);
+}
+
+/*
+ * Interface Management
+ */
+static t_interface_description* interfaceList = NULL;
+
+static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *elftmp, t_elf_interface_description* elfitf) {
+ t_dup_char itfType;
+ t_interface_description* itf;
+ int i;
+
+ itfType = copyElfString(elftmp, elfitf->type);
+ if(itfType == NULL)
+ return NULL;
+
+ // Search if interfane already loaded
+ for(itf = interfaceList; itf != NULL; itf = itf->next) {
+ if(itf->type == itfType) {
+ if (itf->methodNumber != elfitf->methodNumber) {
+ ERROR("When loading component template %s:\n\tNumber of methods in interface type %s\n\tdiffers from previous declaration: was %d, found %d\n",
+ getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), itfType, itf->methodNumber, elfitf->methodNumber, 0, 0);
+ //Do not fail for now for compatibility reason
+ //goto out_itf_type;
+ }
+ if (cmIntensiveCheckState) {
+ for(i = 0; i < itf->methodNumber; i++) {
+ if (cm_StringCompare(itf->methodNames[i], getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), MAX_INTERNAL_STRING_LENGTH) != 0) {
+ ERROR("When loading component template %s:\n"
+ "\tName of method number %d in interface type %s\n"
+ "\tdiffers from previous declaration: previous name was %s, new name found is %s\n",
+ getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), i,
+ itfType, itf->methodNames[i],
+ getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), 0);
+ //Do not fail for now for compatibility reason
+ //goto out_itf_type;
+ }
+ }
+ }
+ itf->referenceCounter++;
+ cm_StringRelease(itfType);
+ return itf;
+ }
+ }
+
+ // Create a new interface if not exists
+ itf = (t_interface_description*)OSAL_Alloc_Zero(sizeof(t_interface_description) + sizeof(t_dup_char) * (elfitf->methodNumber - 1));
+ if(itf == NULL)
+ goto out_itf_type;
+ itf->referenceCounter = 1;
+ itf->type = itfType;
+ itf->methodNumber = elfitf->methodNumber;
+ for(i = 0; i < itf->methodNumber; i++) {
+ itf->methodNames[i] = copyElfString(elftmp, elfitf->methodNames[i]);
+ if(itf->methodNames[i] == NULL)
+ goto out_method;
+ }
+
+ // Put it in Top
+ itf->next = interfaceList;
+ interfaceList = itf;
+
+ return itf;
+
+out_method:
+ for(i = 0; i < itf->methodNumber; i++)
+ cm_StringRelease(itf->methodNames[i]);
+ OSAL_Free(itf);
+out_itf_type:
+ cm_StringRelease(itfType);
+ return NULL;
+}
+
+static void releaseInterfaceDescription(t_interface_description* itf) {
+ if(itf == NULL)
+ return;
+
+ if(--itf->referenceCounter == 0) {
+ int i;
+
+ // Remove it from list
+ if(interfaceList == itf) {
+ interfaceList = interfaceList->next;
+ } else {
+ t_interface_description* prev = interfaceList;
+ while(prev->next != itf)
+ prev = prev->next;
+ prev->next = itf->next;
+ }
+
+ // Destroy interface description
+ for(i = 0; i < itf->methodNumber; i++) {
+ cm_StringRelease(itf->methodNames[i]);
+ }
+ cm_StringRelease(itf->type);
+ OSAL_Free(itf);
+ }
+}
+
+
+t_cm_error cm_ELF_CheckFile(
+ const char *elfdata,
+ t_bool temporaryDescription,
+ t_elfdescription **elfhandlePtr)
+{
+ t_elfdescription *elfhandle;
+ t_tmp_elfdescription elftmp = {0,};
+ t_cm_error error;
+ t_uint32 version;
+ t_uint32 compatibleVersion;
+ int i, j, k;
+
+ /*
+ * Sanity check
+ */
+ if (elfdata[EI_MAG0] != ELFMAG0 ||
+ elfdata[EI_MAG1] != ELFMAG1 ||
+ elfdata[EI_MAG2] != ELFMAG2 ||
+ elfdata[EI_MAG3] != ELFMAG3 ||
+ elfdata[EI_CLASS] != ELFCLASS64)
+ {
+ ERROR("CM_INVALID_ELF_FILE: component file is not a MMDSP ELF file\n", 0, 0, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ }
+
+ /*
+ * Create elf data
+ */
+ if((error = ELF64_LoadComponent(EM_MMDSP_PLUS, elfdata, elfhandlePtr, &elftmp)) != CM_OK)
+ return error;
+
+ elfhandle = *elfhandlePtr;
+
+ elfhandle->temporaryDescription = temporaryDescription;
+
+ version = swap32(elftmp.elfheader->nmfVersion);
+
+ compatibleVersion = (VERSION_MAJOR(version) == VERSION_MAJOR(NMF_VERSION));
+ if(compatibleVersion)
+ {
+ switch(VERSION_MINOR(NMF_VERSION))
+ {
+ case 10: // Compatible with 2.9, 2.10
+ compatibleVersion =
+ (VERSION_MINOR(version) == 9) ||
+ (VERSION_MINOR(version) == 10);
+ break;
+ default: // Strict compatibility 2.x == 2.x
+ compatibleVersion = (VERSION_MINOR(version) == VERSION_MINOR(NMF_VERSION));
+ }
+ }
+
+ if(! compatibleVersion)
+ {
+ ERROR("CM_INVALID_ELF_FILE: incompatible version for Component %d.%d.x != CM:%d.%d.x\n",
+ VERSION_MAJOR(version), VERSION_MINOR(version),
+ VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), 0, 0);
+ error = CM_INVALID_ELF_FILE;
+ goto onerror;
+ }
+
+
+ /*
+ * Commented since to many noise !!!!
+ if(VERSION_PATCH(version) != VERSION_PATCH(NMF_VERSION))
+ {
+ WARNING("CM_INVALID_ELF_FILE: incompatible version, Component:%d.%d.%d != CM:%d.%d.%d\n",
+ VERSION_MAJOR(version), VERSION_MINOR(version), VERSION_PATCH(version),
+ VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), VERSION_PATCH(NMF_VERSION));
+ }
+ */
+
+ if((error = ELF64_ComputeSegment(elfhandle, &elftmp)) != CM_OK)
+ goto onerror;
+
+ //
+ elfhandle->foundedTemplateName = copyElfString(&elftmp, elftmp.elfheader->templateName);
+ if(elfhandle->foundedTemplateName == NULL)
+ goto oom;
+ elfhandle->minStackSize = swap32(elftmp.elfheader->minStackSize);
+
+ // Get Life-cycle memory
+ if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCConstruct, &elfhandle->memoryForConstruct)) != CM_OK)
+ goto onerror;
+ if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStart, &elfhandle->memoryForStart)) != CM_OK)
+ goto onerror;
+ if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStop, &elfhandle->memoryForStop)) != CM_OK)
+ goto onerror;
+ if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCDestroy, &elfhandle->memoryForDestroy)) != CM_OK)
+ goto onerror;
+
+ // Copy attributes information
+ elfhandle->attributeNumber = swap32(elftmp.elfheader->attributeNumber);
+ if(elfhandle->attributeNumber > 0)
+ {
+ elfhandle->attributes =
+ (t_attribute*)OSAL_Alloc_Zero(sizeof(t_attribute) * elfhandle->attributeNumber);
+ if(elfhandle->attributes == NULL)
+ goto oom;
+
+ if(elfhandle->attributeNumber > 0)
+ {
+ t_elf_attribute *attributes = (t_elf_attribute*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->attributes);
+
+ for(i = 0; i < elfhandle->attributeNumber; i++)
+ {
+ elfhandle->attributes[i].name = copyElfString(&elftmp, attributes[i].name);
+ if(elfhandle->attributes[i].name == NULL)
+ goto oom;
+
+ if((error = getMemoryOffset(elfhandle, &elftmp,
+ MEM_DATA,
+ &attributes[i].symbols,
+ &elfhandle->attributes[i].memory)) != CM_OK)
+ goto onerror;
+ LOG_INTERNAL(2, " attribute %s mem=%s offset=%x\n",
+ elfhandle->attributes[i].name,
+ elfhandle->attributes[i].memory.memory->memoryName,
+ elfhandle->attributes[i].memory.offset,
+ 0, 0, 0);
+ }
+ }
+ }
+
+ // Copy properties information
+ elfhandle->propertyNumber = swap32(elftmp.elfheader->propertyNumber);
+ if(elfhandle->propertyNumber > 0)
+ {
+ elfhandle->properties =
+ (t_property*)OSAL_Alloc_Zero(sizeof(t_property) * elfhandle->propertyNumber);
+ if(elfhandle->properties == NULL)
+ goto oom;
+
+ if(elfhandle->propertyNumber > 0)
+ {
+ t_elf_property *properties = (t_elf_property*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->properties);
+
+ for(i = 0; i < elfhandle->propertyNumber; i++)
+ {
+ elfhandle->properties[i].name = copyElfString(&elftmp, properties[i].name);
+ if(elfhandle->properties[i].name == NULL)
+ goto oom;
+
+ elfhandle->properties[i].value = copyElfString(&elftmp, properties[i].value);
+ if(elfhandle->properties[i].value == NULL)
+ goto oom;
+
+ LOG_INTERNAL(3, " property %s = %s\n",
+ elfhandle->properties[i].name,
+ elfhandle->properties[i].value,
+ 0, 0, 0, 0);
+ }
+ }
+ }
+
+ // Copy requires information
+ elfhandle->requireNumber = swap32(elftmp.elfheader->requireNumber);
+ if(elfhandle->requireNumber > 0)
+ {
+ char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->requires);
+
+ elfhandle->requires = (t_interface_require*)OSAL_Alloc_Zero(sizeof(t_interface_require) * elfhandle->requireNumber);
+ if(elfhandle->requires == NULL)
+ goto oom;
+
+ for(i = 0; i < elfhandle->requireNumber; i++)
+ {
+ t_elf_required_interface *require = (t_elf_required_interface*)ref;
+ t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)require->interface);
+
+ elfhandle->requires[i].name = copyElfString(&elftmp, require->name);
+ if(elfhandle->requires[i].name == NULL)
+ goto oom;
+
+ elfhandle->requires[i].requireTypes = require->requireTypes;
+ elfhandle->requires[i].collectionSize = require->collectionSize;
+ elfhandle->requires[i].interface = getInterfaceDescription(&elftmp, interface);
+ if(elfhandle->requires[i].interface == NULL)
+ goto oom;
+
+ LOG_INTERNAL(2, " require %s <%s> %x\n",
+ elfhandle->requires[i].name,
+ elfhandle->requires[i].interface->type,
+ elfhandle->requires[i].requireTypes, 0, 0, 0);
+ CM_ASSERT(elfhandle->requires[i].collectionSize != 0);
+
+ ref = (char*)&require->indexes[0];
+
+ if((elfhandle->requires[i].requireTypes & VIRTUAL_REQUIRE) == 0 &&
+ (elfhandle->requires[i].requireTypes & STATIC_REQUIRE) == 0)
+ {
+ elfhandle->requires[i].indexes =
+ (t_interface_require_index*)OSAL_Alloc_Zero(sizeof(t_interface_require_index) * elfhandle->requires[i].collectionSize);
+ if(elfhandle->requires[i].indexes == NULL)
+ goto oom;
+
+ for(j = 0; j < elfhandle->requires[i].collectionSize; j++)
+ {
+ t_elf_interface_require_index* index = (t_elf_interface_require_index*)ref;
+
+ elfhandle->requires[i].indexes[j].numberOfClient = swap32(index->numberOfClient);
+ if(elfhandle->requires[i].indexes[j].numberOfClient != 0)
+ {
+ elfhandle->requires[i].indexes[j].memories =
+ (t_memory_reference*)OSAL_Alloc(sizeof(t_memory_reference) * elfhandle->requires[i].indexes[j].numberOfClient);
+ if(elfhandle->requires[i].indexes[j].memories == NULL)
+ goto oom;
+
+ for(k = 0; k < elfhandle->requires[i].indexes[j].numberOfClient; k++) {
+ if((error = getMemoryOffset(elfhandle,&elftmp,
+ MEM_DATA,
+ &index->symbols[k],
+ &elfhandle->requires[i].indexes[j].memories[k])) != CM_OK)
+ goto onerror;
+ LOG_INTERNAL(2, " [%d, %d] mem=%s offset=%x\n",
+ j, k,
+ elfhandle->requires[i].indexes[j].memories[k].memory->memoryName,
+ elfhandle->requires[i].indexes[j].memories[k].offset,
+ 0, 0);
+ }
+ }
+
+ ref += sizeof(index->numberOfClient) + elfhandle->requires[i].indexes[j].numberOfClient * sizeof(index->symbols[0]);
+ }
+ }
+ }
+ }
+
+ // Copy provides informations
+ elfhandle->provideNumber = swap32(elftmp.elfheader->provideNumber);
+ if(elfhandle->provideNumber != 0)
+ {
+ elfhandle->provides =
+ (t_interface_provide*)OSAL_Alloc_Zero(sizeof(t_interface_provide) * elfhandle->provideNumber);
+ if(elfhandle->provides == NULL)
+ goto oom;
+
+ if(elfhandle->provideNumber > 0)
+ {
+ char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->provides);
+
+ for(i = 0; i < elfhandle->provideNumber; i++)
+ {
+ t_elf_provided_interface *provide = (t_elf_provided_interface*)ref;
+ t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)provide->interface);
+
+ elfhandle->provides[i].name = copyElfString(&elftmp, provide->name);
+ if(elfhandle->provides[i].name == NULL)
+ goto oom;
+
+ elfhandle->provides[i].provideTypes = provide->provideTypes;
+ elfhandle->provides[i].interruptLine = provide->interruptLine;
+ elfhandle->provides[i].collectionSize = provide->collectionSize;
+ elfhandle->provides[i].interface = getInterfaceDescription(&elftmp, interface);
+ if(elfhandle->provides[i].interface == NULL)
+ goto oom;
+
+ LOG_INTERNAL(2, " provide %s <%s>\n",
+ elfhandle->provides[i].name,
+ elfhandle->provides[i].interface->type,
+ 0,0, 0, 0);
+ CM_ASSERT(elfhandle->provides[i].collectionSize != 0);
+
+ ref = (char*)&provide->methodSymbols[0];
+
+ {
+ t_uint32 *methodSymbols = (t_uint32*)ref;
+
+ elfhandle->provides[i].indexes = (t_interface_provide_index**)OSAL_Alloc_Zero(
+ sizeof(t_interface_provide_index*) * elfhandle->provides[i].collectionSize);
+ if(elfhandle->provides[i].indexes == NULL)
+ goto oom;
+
+ if(elfhandle->provides[i].interface->methodNumber != 0)
+ {
+ for(j = 0; j < elfhandle->provides[i].collectionSize; j++)
+ {
+ elfhandle->provides[i].indexes[j] = (t_interface_provide_index*)OSAL_Alloc(
+ sizeof(t_interface_provide_index) * elfhandle->provides[i].interface->methodNumber);
+ if(elfhandle->provides[i].indexes[j] == NULL)
+ goto oom;
+
+ for(k = 0; k < elfhandle->provides[i].interface->methodNumber; k++)
+ {
+ if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp,
+ methodSymbols++,
+ &elfhandle->provides[i].indexes[j][k].memory)) != CM_OK)
+ goto onerror;
+
+ if(elfhandle->provides[i].indexes[j][k].memory.memory != NULL)
+ LOG_INTERNAL(2, " [%d, %d] method '%s' mem=%s offset=%x\n",
+ j, k,
+ elfhandle->provides[i].interface->methodNames[k],
+ elfhandle->provides[i].indexes[j][k].memory.memory->memoryName,
+ elfhandle->provides[i].indexes[j][k].memory.offset,
+ 0);
+ else
+ LOG_INTERNAL(2, " [%d, %d] method '%s' address=%x\n",
+ j, k,
+ elfhandle->provides[i].interface->methodNames[k],
+ elfhandle->provides[i].indexes[j][k].memory.offset,
+ 0, 0);
+ }
+ }
+ }
+
+ ref += elfhandle->provides[i].collectionSize * elfhandle->provides[i].interface->methodNumber * sizeof(methodSymbols[0]);
+ }
+ }
+ }
+ }
+
+ return CM_OK;
+
+oom:
+ error = CM_NO_MORE_MEMORY;
+onerror:
+ cm_ELF_CloseFile(temporaryDescription, elfhandle);
+ *elfhandlePtr = NULL;
+ return error;
+}
+
+void cm_ELF_ReleaseDescription(
+ t_uint32 requireNumber, t_interface_require *requires,
+ t_uint32 attributeNumber, t_attribute *attributes,
+ t_uint32 propertyNumber, t_property *properties,
+ t_uint32 provideNumber, t_interface_provide *provides)
+{
+ int i, j;
+
+ // Free provides (Number set when array allocated)
+ if(provides != NULL)
+ {
+ for(i = 0; i < provideNumber; i++)
+ {
+ if(provides[i].indexes != NULL)
+ {
+ for(j = 0; j < provides[i].collectionSize; j++)
+ {
+ OSAL_Free(provides[i].indexes[j]);
+ }
+ OSAL_Free(provides[i].indexes);
+ }
+ releaseInterfaceDescription(provides[i].interface);
+ cm_StringRelease(provides[i].name);
+ }
+ OSAL_Free(provides);
+ }
+
+ // Free requires (Number set when array allocated)
+ if(requires != NULL)
+ {
+ for(i = 0; i < requireNumber; i++)
+ {
+ if(requires[i].indexes != 0)
+ {
+ for(j = 0; j < requires[i].collectionSize; j++)
+ {
+ OSAL_Free(requires[i].indexes[j].memories);
+ }
+ OSAL_Free(requires[i].indexes);
+ }
+ releaseInterfaceDescription(requires[i].interface);
+ cm_StringRelease(requires[i].name);
+ }
+ OSAL_Free(requires);
+ }
+
+ // Free properties (Number set when array allocated)
+ if(properties != NULL)
+ {
+ for(i = 0; i < propertyNumber; i++)
+ {
+ cm_StringRelease(properties[i].value);
+ cm_StringRelease(properties[i].name);
+ }
+ OSAL_Free(properties);
+ }
+
+ // Free Attributes (Number set when array allocated)
+ if(attributes != NULL)
+ {
+ for(i = 0; i < attributeNumber; i++)
+ {
+ cm_StringRelease(attributes[i].name);
+ }
+ OSAL_Free(attributes);
+ }
+}
+
+void cm_ELF_CloseFile(
+ t_bool temporaryDescription,
+ t_elfdescription *elfhandle)
+{
+ if(elfhandle == NULL)
+ return;
+
+ if(temporaryDescription && ! elfhandle->temporaryDescription)
+ return;
+
+ // Release description if not moved to template
+ cm_ELF_ReleaseDescription(
+ elfhandle->requireNumber, elfhandle->requires,
+ elfhandle->attributeNumber, elfhandle->attributes,
+ elfhandle->propertyNumber, elfhandle->properties,
+ elfhandle->provideNumber, elfhandle->provides);
+
+ cm_StringRelease(elfhandle->foundedTemplateName);
+
+ ELF64_UnloadComponent(elfhandle);
+}
+
+
+static t_cm_error allocSegment(
+ t_cm_domain_id domainId,
+ t_elfdescription *elfhandle,
+ t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY],
+ t_memory_property property,
+ t_bool isSingleton) {
+ t_memory_id memId;
+ const t_elfmemory *thisMemory; //!< Memory used to determine this
+ const t_elfmemory *codeMemory; //!< Memory used to determine code
+
+ MMDSP_serializeMemories(elfhandle->instanceProperty, &codeMemory, &thisMemory);
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ const t_elfmemory* mapping;
+
+ if(elfhandle->segments[memId].sumSize == 0x0)
+ continue;
+
+ mapping = MMDSP_getMappingById(memId);
+
+ if(
+ (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) ||
+ (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) )
+ {
+ // Allocate segment
+ memories[memId] = cm_DM_Alloc(domainId, mapping->dspMemType,
+ elfhandle->segments[memId].sumSize / mapping->fileEntSize,
+ mapping->memAlignement, TRUE);
+
+ if(memories[memId] == INVALID_MEMORY_HANDLE)
+ {
+ ERROR("CM_NO_MORE_MEMORY(%s): %x too big\n", mapping->memoryName, elfhandle->segments[memId].sumSize / mapping->fileEntSize, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ // Get reference in memory
+ elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]);
+
+ cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr);
+
+ if (isSingleton)
+ cm_DM_SetDefaultDomain(memories[memId], cm_DM_GetDomainCoreId(domainId));
+
+ // Log it
+ LOG_INTERNAL(1, "\t%s%s: 0x%x..+0x%x (0x%x)\n",
+ mapping->memoryName,
+ (thisMemory == mapping) ? "(THIS)" : "",
+ elfhandle->segments[memId].mpcAddr,
+ elfhandle->segments[memId].sumSize / mapping->fileEntSize,
+ elfhandle->segments[memId].hostAddr, 0);
+ }
+ else if(property == MEM_PRIVATE) // Since we allocate private segment, if not allocate, it's a share one
+ {
+ // In order to allow further relocation based on cached address like mpcAddr & hostAddr,
+ // initialize them also !
+
+ // Get reference in memory
+ elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]);
+
+ cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr);
+ }
+ }
+
+ return CM_OK;
+}
+
+/*
+ * Note: in case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeTemplate
+ */
+t_cm_error cm_ELF_LoadTemplate(
+ t_cm_domain_id domainId,
+ t_elfdescription *elfhandle,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY],
+ t_bool isSingleton)
+{
+ t_cm_error error;
+
+ if((error = allocSegment(domainId, elfhandle, sharedMemories, MEM_SHARABLE, isSingleton)) != CM_OK)
+ return error;
+
+ // Load each readonly segment
+ if((error = ELF64_loadSegment(elfhandle, sharedMemories, MEM_SHARABLE)) != CM_OK)
+ return error;
+
+ return CM_OK;
+}
+
+t_cm_error cm_ELF_LoadInstance(
+ t_cm_domain_id domainId,
+ t_elfdescription *elfhandle,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY],
+ t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY],
+ t_bool isSingleton)
+{
+ t_memory_id memId;
+ t_cm_error error;
+
+ // Erase whole memories to make free in case of error
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ privateMemories[memId] = sharedMemories[memId];
+ }
+
+ if((error = allocSegment(domainId, elfhandle, privateMemories, MEM_PRIVATE, isSingleton)) != CM_OK)
+ return error;
+
+ // Load each writable memory
+ if((error = ELF64_loadSegment(elfhandle, privateMemories, MEM_PRIVATE)) != CM_OK)
+ return error;
+
+ return CM_OK;
+}
+
+void cm_ELF_FlushTemplate(
+ t_nmf_core_id coreId,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY])
+{
+ t_memory_id memId;
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ if(sharedMemories[memId] != INVALID_MEMORY_HANDLE)
+ MMDSP_loadedSection(
+ coreId, memId,
+ sharedMemories[memId]);
+ }
+}
+
+void cm_ELF_FlushInstance(
+ t_nmf_core_id coreId,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY],
+ t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY])
+{
+ t_memory_id memId;
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId])
+ MMDSP_loadedSection(
+ coreId, memId,
+ privateMemories[memId]);
+ }
+}
+
+void cm_ELF_FreeInstance(
+ t_nmf_core_id coreId,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY],
+ t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY])
+{
+ t_memory_id memId;
+
+ if(privateMemories == NULL)
+ return;
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId])
+ {
+ MMDSP_unloadedSection(coreId, memId, privateMemories[memId]);
+ cm_DM_Free(privateMemories[memId], TRUE);
+ }
+ }
+}
+
+void cm_ELF_FreeTemplate(
+ t_nmf_core_id coreId,
+ t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY])
+{
+ t_memory_id memId;
+
+ if(sharedMemories == NULL)
+ return;
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ if(sharedMemories[memId] != INVALID_MEMORY_HANDLE)
+ {
+ MMDSP_unloadedSection(coreId, memId, sharedMemories[memId]);
+ cm_DM_Free(sharedMemories[memId], TRUE);
+ }
+ }
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c
new file mode 100644
index 00000000000..5f6641b188d
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+#include <cm/engine/elf/inc/mmdsp.h>
+#include <cm/engine/elf/inc/bfd.h>
+#include <cm/engine/elf/inc/mpcal.h>
+
+#include <cm/engine/component/inc/initializer.h>
+
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/utils/inc/swap.h>
+#include <cm/engine/trace/inc/trace.h>
+
+#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h>
+
+static const t_elfmemory mmdspMemories[NUMBER_OF_MMDSP_MEMORY] = {
+ {0, SDRAM_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "SDRAM_CODE"}, /* 0: Program memory */
+ {1, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "XROM"}, /* 1: Internal X memory */
+ {2, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "YROM"}, /* 2: Y memory */
+ {3, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "SDR0M24"}, /* 5: SDRAM24 */
+ {4, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "SDROM16"}, /* 6: SDRAM16 */
+ {5, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "ESROM24"}, /* 8: ESRAM24 */
+ {6, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "ESROM16"}, /* 9: ESRAM16 */
+ {7, ESRAM_CODE, ESRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "ESRAM_CODE"}, /*10: ESRAM code */
+ {8, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "XRAM"}, /* 1: Internal X memory */
+ {9, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "YRAM"}, /* 2: Y memory */
+ {10, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "SDRAM24"}, /* 5: SDRAM24 */
+ {11, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "SDRAM16"}, /* 6: SDRAM16 */
+ {12, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "ESRAM24"}, /* 8: ESRAM24 */
+ {13, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "ESRAM16"}, /* 9: ESRAM16 */
+ {14, LOCKED_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "LOCKED_CODE"}, /* : .locked */
+};
+
+#define MAX_ELFSECTIONNAME 10
+struct memoryMapping {
+ char *elfSectionName;
+ t_uint32 memoryIndex[MEM_FOR_LAST]; // memoryIndex[t_instance_property]
+};
+
+static const struct memoryMapping mappingmem0[] = {
+ {"mem0.0", {0, 0}},
+ {"mem0.1", {0, 0}},
+ {"mem0.2", {0, 0}}
+};
+static const struct memoryMapping mappingmem10 =
+ {"mem10", {7, 7}};
+static const struct memoryMapping mappinglocked =
+ {".locked", {14, 14}};
+static const struct memoryMapping mappingmem1[] = {
+ {"", {0xff, 0xff}},
+ {"mem1.1", {1, 1}},
+ {"mem1.2", {8, 1}},
+ {"mem1.3", {1, 1}},
+ {"mem1.4", {8, 1}},
+ {"mem1.stack", {8, 1}}
+};
+static const struct memoryMapping mappingmem2[] = {
+ {"", {0xff, 0xff}},
+ {"mem2.1", {2, 2}},
+ {"mem2.2", {9, 2}},
+ {"mem2.3", {2, 2}},
+ {"mem2.4", {9, 2}}
+};
+static const struct memoryMapping mappingmem5[] = {
+ {"", {0xff, 0xff}},
+ {"mem5.1", {3, 3}},
+ {"mem5.2", {10, 3}},
+ {"mem5.3", {3, 3}},
+ {"mem5.4", {10, 3}}
+};
+static const struct memoryMapping mappingmem6[] = {
+ {"", {0xff, 0xff}},
+ {"mem6.1", {4, 4}},
+ {"mem6.2", {11, 4}},
+ {"mem6.3", {4, 4}},
+ {"mem6.4", {11, 4}}
+};
+static const struct memoryMapping mappingmem8[] = {
+ {"", {0xff, 0xff}},
+ {"mem8.1", {5, 5}},
+ {"mem8.2", {12, 5}},
+ {"mem8.3", {5, 5}},
+ {"mem8.4", {12, 5}}
+};
+static const struct memoryMapping mappingmem9[] = {
+ {"", {0xff, 0xff}},
+ {"mem9.1", {6, 6}},
+ {"mem9.2", {13, 6}},
+ {"mem9.3", {6, 6}},
+ {"mem9.4", {13, 6}}
+};
+
+static const struct {
+ const struct memoryMapping* mapping;
+ unsigned int number;
+} hashMappings[10] = {
+ {mappingmem0, sizeof(mappingmem0) / sizeof(mappingmem0[0])},
+ {mappingmem1, sizeof(mappingmem1) / sizeof(mappingmem1[0])},
+ {mappingmem2, sizeof(mappingmem2) / sizeof(mappingmem2[0])},
+ {0x0, 0},
+ {0x0, 0},
+ {mappingmem5, sizeof(mappingmem5) / sizeof(mappingmem5[0])},
+ {mappingmem6, sizeof(mappingmem6) / sizeof(mappingmem6[0])},
+ {0x0, 0},
+ {mappingmem8, sizeof(mappingmem8) / sizeof(mappingmem8[0])},
+ {mappingmem9, sizeof(mappingmem9) / sizeof(mappingmem9[0])},
+};
+
+const t_elfmemory* MMDSP_getMappingById(t_memory_id memId)
+{
+ return &mmdspMemories[memId];
+}
+
+const t_elfmemory* MMDSP_getMappingByName(const char* sectionName, t_instance_property property)
+{
+ if(sectionName[0] == 'm' && sectionName[1] == 'e' && sectionName[2] == 'm')
+ {
+ if(sectionName[4] == '.')
+ {
+ if(sectionName[5] >= '0' && sectionName[5] <= '9')
+ {
+ if(sectionName[3] >= '0' && sectionName[3] <= '9')
+ {
+ unsigned int m, sm;
+
+ m = sectionName[3] - '0';
+ sm = sectionName[5] - '0';
+ if(sm < hashMappings[m].number)
+ return &mmdspMemories[hashMappings[m].mapping[sm].memoryIndex[property]];
+ }
+ } else if(sectionName[3] == '1' && sectionName[5] == 's')
+ return &mmdspMemories[mappingmem1[5].memoryIndex[property]];
+ }
+ else if(sectionName[3] == '1' && sectionName[4] == '0')
+ return &mmdspMemories[mappingmem10.memoryIndex[property]];
+ }
+ else if(sectionName[0] == '.' && sectionName[1] == 'l' && sectionName[2] == 'o' && sectionName[3] == 'c' &&
+ sectionName[4] == 'k' && sectionName[5] == 'e' && sectionName[6] == 'd')
+ {
+ return &mmdspMemories[mappinglocked.memoryIndex[property]];
+ }
+
+ return NULL;
+}
+
+void MMDSP_serializeMemories(t_instance_property property,
+ const t_elfmemory** codeMemory, const t_elfmemory** thisMemory) {
+ // Return meory reference
+ *codeMemory = &mmdspMemories[0];
+ if(property == MEM_FOR_SINGLETON)
+ {
+ *thisMemory = &mmdspMemories[1];
+ }
+ else
+ {
+ *thisMemory = &mmdspMemories[8];
+ }
+}
+
+void MMDSP_copyCode(t_uint64 * remoteAddr64, const char* origAddr, int nb)
+{
+ int m;
+
+ // Linux allow unaligned access
+#ifdef LINUX
+ t_uint64 *origAddr64 = (t_uint64*)origAddr;
+#else
+ __packed t_uint64 *origAddr64 = (__packed t_uint64*)origAddr;
+#endif
+
+ for (m = 0; m < nb; m += 8)
+ {
+ *remoteAddr64++ = swap64(*origAddr64++);
+ }
+}
+
+void MMDSP_copyData24(t_uint32 * remoteAddr32, const char* origAddr, int nb)
+{
+ int m;
+
+ for (m = 0; m < nb; m+=4)
+ {
+ t_uint32 value1;
+
+ value1 = (*origAddr++ << 16);
+ value1 |= (*origAddr++ << 8);
+ value1 |= (*origAddr++ << 0);
+ *remoteAddr32++ = value1;
+ }
+}
+
+void MMDSP_copyData16(t_uint16 * remoteAddr16, const char* origAddr, int nb)
+{
+ int m;
+
+ for (m = 0; m < nb; m+=2)
+ {
+ t_uint16 value1;
+
+ origAddr++; // Skip this byte (which is put in elf file for historical reason)
+ value1 = (*origAddr++ << 8);
+ value1 |= (*origAddr++ << 0);
+ *remoteAddr16++ = value1;
+ }
+}
+
+#if 0
+__asm void MMDSP_copyCode(void* dst, const void* src, int nb)
+{
+ PUSH {r4-r8, lr}
+ SUBS r2,r2,#0x20
+ BCC l4
+
+l5
+ SETEND BE
+ LDR r4, [r1], #0x4
+ LDR r3, [r1], #0x4
+ LDR r6, [r1], #0x4
+ LDR r5, [r1], #0x4
+ LDR r8, [r1], #0x4
+ LDR r7, [r1], #0x4
+ LDR lr, [r1], #0x4
+ LDR r12, [r1], #0x4
+
+ SETEND LE
+ STM r0!,{r3-r8,r12, lr}
+ SUBS r2,r2,#0x20
+ BCS l5
+
+l4
+ LSLS r12,r2,#28
+
+ SETEND BE
+ LDRCS r4, [r1], #0x4
+ LDRCS r3, [r1], #0x4
+ LDRCS r6, [r1], #0x4
+ LDRCS r5, [r1], #0x4
+ SETEND LE
+ STMCS r0!,{r3-r6}
+
+ SETEND BE
+ LDRMI r4, [r1], #0x4
+ LDRMI r3, [r1], #0x4
+ SETEND LE
+ STMMI r0!,{r3-r4}
+
+ POP {r4-r8, pc}
+}
+#endif
+
+#ifdef LINUX
+static void PLD5(int r)
+{
+ asm volatile (
+ "PLD [r0, #0x20] \n\t"
+ "PLD [r0, #0x40] \n\t"
+ "PLD [r0, #0x60] \n\t"
+ "PLD [r0, #0x80] \n\t"
+ "PLD [r0, #0xA0]" );
+}
+
+static void PLD1(int r)
+{
+ asm volatile (
+ "PLD [r0, #0xC0]" );
+}
+#else /* Symbian, Think -> We assume ARMCC */
+static __asm void PLD5(int r)
+{
+ PLD [r0, #0x20]
+ PLD [r0, #0x40]
+ PLD [r0, #0x60]
+ PLD [r0, #0x80]
+ PLD [r0, #0xA0]
+
+ bx lr
+}
+
+static __asm void PLD1(int r)
+{
+ PLD [r0, #0xC0]
+
+ bx lr
+}
+#endif
+
+#if 0
+__asm void COPY(void* dst, const void* src, int nb)
+{
+ PUSH {r4-r8, lr}
+ SUBS r2,r2,#0x20
+ BCC l4a
+ PLD [r1, #0x20]
+ PLD [r1, #0x40]
+ PLD [r1, #0x60]
+ PLD [r1, #0x80]
+ PLD [r1, #0xA0]
+
+l5a
+ PLD [r1, #0xC0]
+ LDM r1!,{r3-r8,r12,lr}
+ STM r0!,{r3-r8,r12,lr}
+ SUBS r2,r2,#0x20
+ BCS l5a
+
+l4a
+ LSLS r12,r2,#28
+ LDMCS r1!,{r3,r4,r12,lr}
+ STMCS r0!,{r3,r4,r12,lr}
+ LDMMI r1!,{r3,r4}
+ STMMI r0!,{r3,r4}
+ POP {r4-r8,lr}
+ LSLS r12,r2,#30
+ LDRCS r3,[r1],#4
+ STRCS r3,[r0],#4
+ BXEQ lr
+l6b
+ LSLS r2,r2,#31
+ LDRHCS r3,[r1],#2
+ LDRBMI r2,[r1],#1
+ STRHCS r3,[r0],#2
+ STRBMI r2,[r0],#1
+ BX lr
+}
+#endif
+
+
+void MMDSP_copySection(t_uint32 origAddr, t_uint32 remoteAddr, t_uint32 sizeInByte) {
+ t_uint32 endAddr = remoteAddr + sizeInByte;
+
+ PLD5(origAddr);
+
+ // Align on 32bits
+ if((remoteAddr & 0x3) != 0)
+ {
+ *(t_uint16*)remoteAddr = *(t_uint16*)origAddr;
+ remoteAddr += sizeof(t_uint16);
+ origAddr += sizeof(t_uint16);
+ }
+
+ // Align on 64bits
+ if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32)))
+ {
+ *(t_uint32*)remoteAddr = *(t_uint32*)origAddr;
+ remoteAddr += sizeof(t_uint32);
+ origAddr += sizeof(t_uint32);
+ }
+
+ // 64bits burst access
+ for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64), origAddr += sizeof(t_uint64))
+ {
+ PLD1(origAddr);
+ *(volatile t_uint64*)remoteAddr = *(t_uint64*)origAddr;
+ }
+
+ // Remain 32bits access
+ if(remoteAddr <= endAddr - sizeof(t_uint32))
+ {
+ *(t_uint32*)remoteAddr = *(t_uint32*)origAddr;
+ remoteAddr += sizeof(t_uint32);
+ origAddr += sizeof(t_uint32);
+ }
+
+ // Remain 16bits access
+ if(remoteAddr <= endAddr - sizeof(t_uint16))
+ *(t_uint16*)remoteAddr = *(t_uint16*)origAddr;
+}
+
+
+void MMDSP_bzeroSection(t_uint32 remoteAddr, t_uint32 sizeInByte) {
+ t_uint32 endAddr = remoteAddr + sizeInByte;
+
+ // Align on 32bits
+ if((remoteAddr & 0x3) != 0)
+ {
+ *(t_uint16*)remoteAddr = 0;
+ remoteAddr += sizeof(t_uint16);
+ }
+
+ // Align on 64bits
+ if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32)))
+ {
+ *(t_uint32*)remoteAddr = 0;
+ remoteAddr += sizeof(t_uint32);
+ }
+
+ // 64bits burst access
+ for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64))
+ *(volatile t_uint64*)remoteAddr = 0ULL;
+
+ // Remain 32bits access
+ if(remoteAddr <= endAddr - sizeof(t_uint32))
+ {
+ *(t_uint32*)remoteAddr = 0;
+ remoteAddr += sizeof(t_uint32);
+ }
+
+ // Remain 16bits access
+ if(remoteAddr <= endAddr - sizeof(t_uint16))
+ *(t_uint16*)remoteAddr = 0;
+}
+
+void MMDSP_loadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle)
+{
+ if(mmdspMemories[memId].purpose == MEM_CODE)
+ {
+ OSAL_CleanDCache(cm_DSP_GetHostLogicalAddress(handle), cm_MM_GetSize(handle));
+ }
+
+ if(memId == LOCKED_CODE)
+ {
+ t_uint32 DspAddress, DspSize;
+
+ cm_DSP_GetDspMemoryHandleSize(handle, &DspSize);
+ cm_DSP_GetDspAddress(handle, &DspAddress);
+
+ cm_COMP_InstructionCacheLock(coreId, DspAddress, DspSize);
+ }
+}
+
+void MMDSP_unloadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle)
+{
+ if(memId == LOCKED_CODE)
+ {
+ t_uint32 DspAddress, DspSize;
+
+ cm_DSP_GetDspMemoryHandleSize(handle, &DspSize);
+ cm_DSP_GetDspAddress(handle, &DspAddress);
+
+ cm_COMP_InstructionCacheUnlock(coreId, DspAddress, DspSize);
+ }
+
+}
+
+static struct reloc_howto_struct elf64_mmdsp_howto_table[] =
+{
+ HOWTO (R_MMDSP_IMM20_16, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 8, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0x0, /* special_function */
+ "R_MMDSP_IMM20_16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0000000000ffff00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 4-bit absolute relocation for splitted 20 bits immediate, shifted by 56 */
+
+ HOWTO (R_MMDSP_IMM20_4, /* type */
+ 16, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 4, /* bitsize */
+ FALSE, /* pc_relative */
+ 56, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0x0, /* special_function */
+ "R_MMDSP_IMM20_4", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0f00000000000000LL, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MMDSP_24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0x0, /* special_function */
+ "R_MMDSP_24", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MMDSP_IMM16, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 8, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0x0, /* special_function */
+ "R_MMDSP_IMM16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0000000000ffff00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+};
+
+static const char* lastInPlaceAddr = 0;
+static long long lastInPlaceValue;
+
+void MMDSP_performRelocation(
+ t_uint32 type,
+ const char* symbol_name,
+ t_uint32 symbol_addr,
+ char* reloc_addr,
+ const char* inPlaceAddr,
+ t_uint32 reloc_offset) {
+ int i;
+
+ for(i = 0; i < sizeof(elf64_mmdsp_howto_table) / sizeof(elf64_mmdsp_howto_table[0]); i++)
+ {
+ struct reloc_howto_struct* howto = &elf64_mmdsp_howto_table[i];
+ if(howto->type == type)
+ {
+ t_uint64 relocation;
+
+ LOG_INTERNAL(2, "reloc '%s:0x%x' type %s at 0x%x (0x%x)\n",
+ symbol_name ? symbol_name : "??", symbol_addr,
+ howto->name,
+ reloc_offset, reloc_addr, 0);
+
+ relocation = symbol_addr;
+
+ if (howto->pc_relative) {
+ // Not handle yet
+ }
+
+ if (howto->complain_on_overflow != complain_overflow_dont) {
+ // Not handle yet
+ }
+
+ relocation >>= howto->rightshift;
+
+ relocation <<= howto->bitpos;
+
+#define DOIT(x) \
+ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
+
+ switch (howto->size) {
+ case 2: {
+ long x = *(long*)inPlaceAddr;
+
+ // CM_ASSERT(*(long*)inPlaceAddr == *(long*)reloc_addr);
+
+ DOIT (x);
+ *(long*)reloc_addr = x;
+ }
+ break;
+ case 4: {
+ long long x;
+ if(lastInPlaceAddr == inPlaceAddr)
+ {
+ x = lastInPlaceValue;
+ }
+ else
+ {
+ // CM_ASSERT(*(__packed long long*)inPlaceAddr == *(long long*)reloc_addr);
+ x = *(long long*)inPlaceAddr;
+ lastInPlaceAddr = inPlaceAddr;
+ }
+
+ DOIT (x);
+ *(long long*)reloc_addr = lastInPlaceValue = x;
+ }
+ break;
+ default:
+ CM_ASSERT(0);
+ }
+
+ return;
+ }
+ }
+
+ ERROR("Relocation type %d not supported for '%s'\n", type, symbol_name, 0, 0, 0, 0);
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c
new file mode 100644
index 00000000000..b08ac6a361e
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+/*
+ *
+ */
+#include <cm/engine/elf/inc/bfd.h>
+#include <cm/engine/elf/inc/mpcal.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/utils/inc/string.h>
+
+t_cm_error cm_ELF_relocateSharedSegments(
+ t_memory_handle *memories,
+ t_elfdescription *elfhandle,
+ void *cbContext)
+{
+ return ELF64_relocateSegments(
+ memories,
+ elfhandle,
+ MEM_SHARABLE,
+ cbContext);
+}
+
+t_cm_error cm_ELF_relocatePrivateSegments(
+ t_memory_handle *memories,
+ t_elfdescription *elfhandle,
+ void *cbContext)
+{
+ return ELF64_relocateSegments(
+ memories,
+ elfhandle,
+ MEM_PRIVATE,
+ cbContext);
+}
+
+void cm_ELF_performRelocation(
+ t_uint32 type,
+ const char* symbol_name,
+ t_uint32 symbol_addr,
+ char* reloc_addr)
+{
+ MMDSP_performRelocation(
+ type,
+ symbol_name,
+ symbol_addr,
+ reloc_addr,
+ reloc_addr,
+ 0xBEEF);
+
+ OSAL_CleanDCache((t_uint32)reloc_addr, 8);
+}
+
+t_cm_error cm_ELF_GetMemory(
+ t_elfdescription *elf,
+ t_tmp_elfdescription *elftmp,
+ t_uint32 address,
+ t_memory_purpose purpose,
+ t_memory_reference *memory) {
+ t_memory_id memId;
+
+ for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++)
+ {
+ const t_elfmemory* mem = MMDSP_getMappingById(memId);
+
+ if(mem->purpose == purpose && // Memory correspond
+ elf->segments[mem->id].sumSize != 0 && // Segment allocated
+ (elf->segments[mem->id].mpcAddr <= address) &&
+ (address < elf->segments[mem->id].mpcAddr + elf->segments[mem->id].sumSize / mem->fileEntSize)) {
+ memory->memory = mem;
+ memory->offset = address - elf->segments[mem->id].mpcAddr;
+ return CM_OK;
+ }
+ }
+
+ ERROR("Memory %x,%d not found\n", address, purpose, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c
new file mode 100644
index 00000000000..4a2976a6bc1
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+#include <cm/engine/elf/inc/mpcal.h>
+
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/utils/inc/mem.h>
+
+
+static t_uint32 max(t_uint32 a, t_uint32 b)
+{
+ return (a >= b) ? a : b;
+}
+/*
+static t_uint32 min(t_uint32 a, t_uint32 b)
+{
+ return (a <= b) ? a : b;
+}
+*/
+
+struct XXrelocation
+{
+ t_uint32 st_value;
+ ElfXX_Half st_shndx;
+ Elf64_Sxword r_addend;
+ t_uint32 OffsetInElf;
+ t_uint32 type;
+
+ t_dup_char symbol_name; // Valid only if st_shndx == SHN_UNDEF
+};
+
+struct XXSection {
+ ElfXX_Word sh_type; /* Section type */
+ t_uint32 sh_size; /* Section size in bytes */
+ ElfXX_Word sh_info; /* Additional section information */
+ ElfXX_Word sh_link; /* Link to another section */
+ t_uint32 sh_addralign; /* Some sections have address alignment constraints */
+ t_uint32 sh_addr; /* Section addr */
+ ElfXX_Xword sh_flags; /* Section flags */
+
+ const char *data;
+ t_uint32 trueDataSize; /* Valid if different from sh_size */
+ const char *sectionName;
+
+ t_uint32 offsetInSegment;
+ const t_elfmemory *meminfo;
+
+ t_uint32 relocationNumber;
+ struct XXrelocation *relocations;
+};
+
+struct XXElf {
+ t_uint32 e_shnum;
+ struct XXSection sectionss[1];
+};
+
+t_cm_error ELF64_LoadComponent(
+ t_uint16 e_machine,
+ const char *elfdata,
+ t_elfdescription **elfhandlePtr,
+ t_tmp_elfdescription *elftmp)
+{
+ t_elfdescription *elfhandle;
+ const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elfdata;
+ const ElfXX_Shdr *sections;
+ const char *strings;
+ struct XXElf* ELF;
+ int i, nb;
+
+ elftmp->elfdata = elfdata;
+
+ /* Sanity check */
+ if (swapHalf(header->e_machine) != e_machine)
+ {
+ ERROR("This is not a executable for such MPC\n", 0, 0, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ }
+
+ // Cache elf file informations
+ nb = swapHalf(header->e_shnum);
+ elftmp->isExecutable = (swapHalf(header->e_type) == ET_EXEC);
+
+ elfhandle = (t_elfdescription*)OSAL_Alloc_Zero(
+ sizeof(t_elfdescription) + sizeof(struct XXElf) + sizeof(struct XXSection) * (nb - 1));
+ if(elfhandle == NULL)
+ return CM_NO_MORE_MEMORY;
+
+ ELF = elfhandle->ELF = (struct XXElf*)(elfhandle + 1);
+
+ ELF->e_shnum = nb;
+
+ sections = (ElfXX_Shdr*)&elfdata[swapXword(header->e_shoff)];
+ // Compute and swap section infromation
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ ELF->sectionss[i].sh_type = swapWord(sections[i].sh_type);
+ ELF->sectionss[i].sh_info = swapWord(sections[i].sh_info);
+ ELF->sectionss[i].sh_link = swapWord(sections[i].sh_link);
+ ELF->sectionss[i].sh_size = (t_uint32)swapXword(sections[i].sh_size);
+ ELF->sectionss[i].sh_addralign = (t_uint32)swapXword(sections[i].sh_addralign);
+ ELF->sectionss[i].sh_addr = (t_uint32)swapXword(sections[i].sh_addr);
+ ELF->sectionss[i].sh_flags = swapXword(sections[i].sh_flags);
+
+ elftmp->sectionData[i] = &elfdata[(t_uint32)swapXword(sections[i].sh_offset)];
+ }
+
+ /*
+ * search nmf_segment
+ */
+ strings = elftmp->sectionData[swapHalf(header->e_shstrndx)];
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ ELF->sectionss[i].sectionName = &strings[swapWord(sections[i].sh_name)];
+
+ // Found nmf_segment to see if it's
+ if(cm_StringCompare("nmf_segment", ELF->sectionss[i].sectionName, 11) == 0) {
+ elftmp->nmfSectionIndex = i;
+ elftmp->elfheader = (const t_elf_component_header*)elftmp->sectionData[i];
+ }
+ }
+
+ if(elftmp->nmfSectionIndex == 0)
+ {
+ ERROR("This is not a NMF component\n", 0, 0, 0, 0, 0, 0);
+ goto invalid;
+ }
+
+ /*
+ * Determine component type
+ */
+ elfhandle->magicNumber = swap32(elftmp->elfheader->magic);
+ switch(elfhandle->magicNumber) {
+ case MAGIC_COMPONENT:
+ elfhandle->instanceProperty = MEM_FOR_MULTIINSTANCE;
+ break;
+ case MAGIC_SINGLETON:
+ case MAGIC_FIRMWARE:
+ elfhandle->instanceProperty = MEM_FOR_SINGLETON;
+ break;
+ }
+
+ // Copy content
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ ELF->sectionss[i].meminfo = MMDSP_getMappingByName(
+ ELF->sectionss[i].sectionName,
+ elfhandle->instanceProperty);
+
+ if(ELF->sectionss[i].meminfo != NULL)
+ ELF->sectionss[i].trueDataSize = (ELF->sectionss[i].sh_size / ELF->sectionss[i].meminfo->fileEntSize) * ELF->sectionss[i].meminfo->memEntSize;
+
+ if(ELF->sectionss[i].sh_size != 0 &&
+ ELF->sectionss[i].sh_type == SHT_PROGBITS &&
+ (ELF->sectionss[i].sh_flags & SHF_ALLOC) != 0)
+ {
+ const char* elfAddr = elftmp->sectionData[i];
+
+ ELF->sectionss[i].data = OSAL_Alloc(ELF->sectionss[i].trueDataSize);
+ if(ELF->sectionss[i].data == NULL)
+ goto oom;
+
+ if(ELF->sectionss[i].meminfo->purpose == MEM_CODE)
+ {
+ MMDSP_copyCode(
+ (t_uint64*)ELF->sectionss[i].data,
+ elfAddr,
+ ELF->sectionss[i].trueDataSize);
+ }
+ else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA &&
+ // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 &&
+ ELF->sectionss[i].meminfo->memEntSize == 4)
+ {
+ MMDSP_copyData24(
+ (t_uint32*)ELF->sectionss[i].data,
+ elfAddr,
+ ELF->sectionss[i].trueDataSize);
+ }
+ else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA &&
+ // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 &&
+ ELF->sectionss[i].meminfo->memEntSize == 2)
+ {
+ MMDSP_copyData16(
+ (t_uint16*)ELF->sectionss[i].data,
+ elfAddr,
+ ELF->sectionss[i].trueDataSize);
+ }
+ else
+ CM_ASSERT(0);
+ }
+ }
+
+ // Copy relocation
+ // Loop on all relocation section
+ for(i=0; i < ELF->e_shnum; i++)
+ {
+ int sh_info;
+
+ // Does this section is a relocation table (only RELA supported)
+ if((ELF->sectionss[i].sh_type != SHT_RELA) ||
+ ELF->sectionss[i].sh_size == 0) continue;
+
+ // Copy only relocation for loaded section
+ sh_info = ELF->sectionss[i].sh_info;
+ if(ELF->sectionss[sh_info].meminfo != NULL)
+ {
+ const ElfXX_Sym* symtab;
+ const char* strtab;
+ ElfXX_Rela* rel_start;
+ int n;
+
+ ELF->sectionss[sh_info].relocationNumber = ELF->sectionss[i].sh_size / sizeof(ElfXX_Rela);
+ ELF->sectionss[sh_info].relocations = (struct XXrelocation*)OSAL_Alloc_Zero(sizeof(struct XXrelocation) * ELF->sectionss[sh_info].relocationNumber);
+ if(ELF->sectionss[sh_info].relocations == NULL)
+ goto oom;
+
+ symtab = (ElfXX_Sym *)elftmp->sectionData[ELF->sectionss[i].sh_link];
+ strtab = elftmp->sectionData[ELF->sectionss[ELF->sectionss[i].sh_link].sh_link];
+ rel_start = (ElfXX_Rela*)elftmp->sectionData[i];
+ for(n = 0; n < ELF->sectionss[sh_info].relocationNumber; n++, rel_start++)
+ {
+ struct XXrelocation* relocation = &ELF->sectionss[sh_info].relocations[n];
+ ElfXX_Xword r_info = swapXword(rel_start->r_info);
+ int strtab_index = ELFXX_R_SYM(r_info);
+ const char* symbol_name = &strtab[swapWord(symtab[strtab_index].st_name)];
+
+ relocation->st_shndx = swapHalf(symtab[strtab_index].st_shndx);
+ relocation->st_value = (t_uint32)swapXword(symtab[strtab_index].st_value);
+ relocation->r_addend = swapXword(rel_start->r_addend);
+ relocation->OffsetInElf = (t_uint32)swapXword(rel_start->r_offset) / ELF->sectionss[sh_info].meminfo->fileEntSize;
+ relocation->type = ELFXX_R_TYPE(r_info);
+
+ switch(relocation->st_shndx) {
+ case SHN_UNDEF:
+ relocation->symbol_name = cm_StringDuplicate(symbol_name + 1); /* Remove '_' prefix */
+ if(relocation->symbol_name == NULL)
+ goto oom;
+ break;
+ case SHN_COMMON:
+ ERROR("SHN_COMMON not handle for %s\n", symbol_name, 0, 0, 0, 0, 0);
+ goto invalid;
+ }
+ }
+ }
+ }
+
+ *elfhandlePtr = elfhandle;
+ return CM_OK;
+invalid:
+ ELF64_UnloadComponent(elfhandle);
+ return CM_INVALID_ELF_FILE;
+oom:
+ ELF64_UnloadComponent(elfhandle);
+ return CM_NO_MORE_MEMORY;
+}
+
+t_cm_error ELF64_ComputeSegment(
+ t_elfdescription *elfhandle,
+ t_tmp_elfdescription *elftmp)
+{
+ struct XXElf* ELF = elfhandle->ELF;
+ int i;
+
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ ELF->sectionss[i].offsetInSegment = 0xFFFFFFFF;
+
+ if(ELF->sectionss[i].sh_type == SHT_PROGBITS || ELF->sectionss[i].sh_type == SHT_NOBITS) {
+ // This is a loadable memory (memory size could be zero since we can have symbol on it)...
+ const t_elfmemory* meminfo = ELF->sectionss[i].meminfo;
+
+ if(meminfo != NULL) {
+ // Which correspond to MPC memory
+
+ if(elftmp->isExecutable)
+ {
+ if(! elfhandle->segments[meminfo->id].sumSizeSetted)
+ {
+ CM_ASSERT(ELF->sectionss[i].sh_addr >= meminfo->startAddr * meminfo->fileEntSize);
+
+ elfhandle->segments[meminfo->id].sumSizeSetted = TRUE;
+ elfhandle->segments[meminfo->id].sumSize = ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize;
+ }
+ else
+ CM_ASSERT(elfhandle->segments[meminfo->id].sumSize == ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize);
+ }
+ else
+ {
+ while(elfhandle->segments[meminfo->id].sumSize % ELF->sectionss[i].sh_addralign != 0)
+ elfhandle->segments[meminfo->id].sumSize++;
+ }
+
+ elfhandle->segments[meminfo->id].maxAlign = max(elfhandle->segments[meminfo->id].maxAlign, ELF->sectionss[i].sh_addralign);
+ ELF->sectionss[i].offsetInSegment = elfhandle->segments[meminfo->id].sumSize / meminfo->fileEntSize;
+ elfhandle->segments[meminfo->id].sumSize += ELF->sectionss[i].sh_size;
+ }
+ } else if(ELF->sectionss[i].sh_type == SHT_RELA && ELF->sectionss[i].sh_info == elftmp->nmfSectionIndex) {
+ int secsym = ELF->sectionss[i].sh_link;
+ elftmp->relaNmfSegment = (ElfXX_Rela*)elftmp->sectionData[i];
+ elftmp->relaNmfSegmentEnd = (ElfXX_Rela*)((t_uint32)elftmp->relaNmfSegment + ELF->sectionss[i].sh_size);
+ elftmp->relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->sectionData[secsym];
+ elftmp->relaNmfSegmentStrings = elftmp->sectionData[ELF->sectionss[secsym].sh_link];
+ }
+ }
+
+ return CM_OK;
+}
+
+void ELF64_UnloadComponent(
+ t_elfdescription *elfhandle)
+{
+ struct XXElf* ELF = elfhandle->ELF;
+ int i, n;
+
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ if(ELF->sectionss[i].relocations != NULL)
+ {
+ for(n = 0; n < ELF->sectionss[i].relocationNumber; n++)
+ cm_StringRelease(ELF->sectionss[i].relocations[n].symbol_name);
+ OSAL_Free(ELF->sectionss[i].relocations);
+ }
+
+ OSAL_Free((void*)ELF->sectionss[i].data);
+ }
+ OSAL_Free(elfhandle);
+}
+
+t_cm_error ELF64_loadSegment(
+ t_elfdescription *elfhandle,
+ t_memory_handle *memory,
+ t_memory_property property)
+{
+ struct XXElf* ELF = elfhandle->ELF;
+ int i;
+
+ /*
+ * Copy ELF data in this segment
+ */
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ const t_elfmemory* mapping = ELF->sectionss[i].meminfo;
+
+ if(mapping == NULL)
+ continue;
+ if((! (ELF->sectionss[i].sh_flags & SHF_ALLOC)) || (ELF->sectionss[i].sh_size == 0))
+ continue;
+
+ // This is a loadable memory ...
+ if(
+ (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) ||
+ (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) )
+ {
+ // Where memory exist and waited share/private correspond
+ t_uint32 remoteData = elfhandle->segments[mapping->id].hostAddr +
+ ELF->sectionss[i].offsetInSegment * mapping->memEntSize;
+
+ if(ELF->sectionss[i].sh_type != SHT_NOBITS)
+ {
+ LOG_INTERNAL(2, "loadSection(%s, 0x%x, 0x%x, 0x%08x)\n",
+ ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize,
+ (t_uint32)ELF->sectionss[i].data, 0, 0);
+
+ MMDSP_copySection((t_uint32)ELF->sectionss[i].data, remoteData, ELF->sectionss[i].trueDataSize);
+ }
+ else
+ {
+ LOG_INTERNAL(2, "bzeroSection(%s, 0x%x, 0x%x)\n",
+ ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, 0, 0, 0);
+
+ MMDSP_bzeroSection(remoteData, ELF->sectionss[i].trueDataSize);
+ }
+ }
+ }
+
+ return CM_OK;
+}
+
+
+
+static const t_elfmemory* getSectionAddress(
+ t_memory_handle *memories,
+ t_elfdescription *elfhandle,
+ t_uint32 sectionIdx,
+ t_uint32 *sectionOffset,
+ t_cm_logical_address *sectionAddr) {
+ struct XXElf* ELF = elfhandle->ELF;
+ const t_elfmemory* mapping = ELF->sectionss[sectionIdx].meminfo;
+
+ if(mapping != NULL) {
+ *sectionOffset = (elfhandle->segments[mapping->id].mpcAddr +
+ ELF->sectionss[sectionIdx].offsetInSegment);
+
+ *sectionAddr = (t_cm_logical_address)(elfhandle->segments[mapping->id].hostAddr +
+ ELF->sectionss[sectionIdx].offsetInSegment * mapping->memEntSize);
+ }
+
+ return mapping;
+}
+
+static t_uint32 getSymbolAddress(
+ t_memory_handle *memories,
+ t_elfdescription *elfhandle,
+ t_uint32 symbolSectionIdx,
+ t_uint32 symbolOffet) {
+ struct XXElf* ELF = elfhandle->ELF;
+ const t_elfmemory* mapping = ELF->sectionss[symbolSectionIdx].meminfo;
+
+ if(mapping == NULL)
+ return 0xFFFFFFFF;
+ // CM_ASSERT(elfhandle->segments[mapping->id].sumSize != 0);
+ // CM_ASSERT(elfhandle->sections[symbolSectionIdx].offsetInSegment != 0xFFFFFFFF);
+
+ return elfhandle->segments[mapping->id].mpcAddr +
+ ELF->sectionss[symbolSectionIdx].offsetInSegment +
+ symbolOffet;
+}
+
+#if 0
+t_bool ELFXX_getSymbolLocation(
+ const t_mpcal_memory *mpcalmemory,
+ t_elfdescription *elf,
+ char *symbolName,
+ const t_elfmemory **memory,
+ t_uint32 *offset) {
+ const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elf->elfdata;
+ const ElfXX_Shdr *sections = (ElfXX_Shdr*)&elf->elfdata[swapXword(header->e_shoff)];
+ const char *strings = &elf->elfdata[swapXword(sections[swapHalf(header->e_shstrndx)].sh_offset)];
+ int len = cm_StringLength(symbolName, 256); // TO BE FIXED
+ int i;
+
+ for(i = 0; i < ELF->e_shnum; i++)
+ {
+ ElfXX_Sym* symtab;
+ const char* strtab;
+ unsigned int size, j;
+
+ if(ELF->sectionss[i].sh_type != SHT_SYMTAB && ELF->sectionss[i].sh_type != SHT_DYNSYM) continue;
+
+ // Section is a symbol table
+ symtab = (ElfXX_Sym*)&elf->elfdata[swapXword(sections[i].sh_offset)];
+ strtab = &elf->elfdata[swapXword(sections[swapWord(sections[i].sh_link)].sh_offset)];
+ size = ELF->sectionss[i].sh_size / (unsigned int)swapXword(sections[i].sh_entsize);
+
+ for(j = 0; j < size; j++) {
+ const char* foundName = &strtab[swapWord(symtab[j].st_name)];
+
+ if(cm_StringCompare(symbolName, foundName, len) == 0) {
+ if(swapHalf(symtab[j].st_shndx) != SHN_UNDEF) {
+ int sectionIdx = (int)swapHalf(symtab[j].st_shndx);
+ ElfXX_Xword sh_flags = swapXword(sections[sectionIdx].sh_flags);
+
+ *memory = mpcalmemory->getMappingByName(&strings[swapWord(sections[sectionIdx].sh_name)],
+ sh_flags & SHF_WRITE ? MEM_RW : (sh_flags & SHF_EXECINSTR ? MEM_X : MEM_RO));
+ *offset = (t_uint32)swapXword(symtab[j].st_value);
+
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+t_cm_error ELF64_relocateSegments(
+ t_memory_handle *memories,
+ t_elfdescription *elfhandle,
+ t_memory_property property,
+ void *cbContext) {
+ struct XXElf* ELF = elfhandle->ELF;
+ int sec, n;
+
+ // Loop on all relocation section
+ for(sec=0; sec < ELF->e_shnum; sec++)
+ {
+ t_cm_logical_address sectionAddr = 0;
+ t_uint32 sectionOffset = 0;
+ const t_elfmemory* mapping;
+
+ if(ELF->sectionss[sec].relocations == NULL)
+ continue;
+
+ // Relocate only section in memory
+ mapping = getSectionAddress(memories,
+ elfhandle,
+ sec,
+ &sectionOffset,
+ &sectionAddr);
+ if(mapping == NULL)
+ continue;
+
+ if(
+ (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) ||
+ (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) )
+ {
+ LOG_INTERNAL(2, "relocSection(%s)\n", ELF->sectionss[sec].sectionName, 0, 0, 0, 0, 0);
+
+ for(n = 0; n < ELF->sectionss[sec].relocationNumber; n++)
+ {
+ struct XXrelocation* relocation = &ELF->sectionss[sec].relocations[n];
+ t_uint32 symbol_addr;
+ char* relocAddr = (char*)(sectionAddr + relocation->OffsetInElf * mapping->memEntSize);
+
+ switch(relocation->st_shndx) {
+ case SHN_ABS: // Absolute external reference
+ symbol_addr = relocation->st_value;
+ break;
+ case SHN_UNDEF: // External reference
+ // LOG_INTERNAL(0, "cm_resolvSymbol(%d, %s)\n", relocation->type, relocation->symbol_name, 0,0, 0, 0);
+ symbol_addr = cm_resolvSymbol(cbContext,
+ relocation->type,
+ relocation->symbol_name,
+ relocAddr);
+ if(symbol_addr == 0x0) { // Not defined symbol
+ ERROR("Symbol %s not found\n", relocation->symbol_name, 0, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ } else if(symbol_addr == 0xFFFFFFFE) { // OOM
+ return CM_NO_MORE_MEMORY;
+ } else if(symbol_addr == 0xFFFFFFFF) { // Defined inside static binding
+ continue;
+ }
+ break;
+ default: // Internal reference in loaded section
+ symbol_addr = getSymbolAddress(
+ memories,
+ elfhandle,
+ (t_uint32)relocation->st_shndx,
+ relocation->st_value);
+ if(symbol_addr == 0xFFFFFFFF) {
+ ERROR("Symbol in section %s+%d not loaded\n",
+ ELF->sectionss[relocation->st_shndx].sectionName,
+ relocation->st_value, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ }
+ break;
+ }
+
+ symbol_addr += relocation->r_addend;
+
+ MMDSP_performRelocation(
+ relocation->type,
+ relocation->symbol_name,
+ symbol_addr,
+ relocAddr,
+ ELF->sectionss[sec].data + relocation->OffsetInElf * mapping->memEntSize,
+ sectionOffset + relocation->OffsetInElf);
+ }
+ }
+ }
+
+ return CM_OK;
+}
+
+t_cm_error ELF64_getRelocationMemory(
+ t_elfdescription *elfhandle,
+ t_tmp_elfdescription *elftmp,
+ t_uint32 offsetInNmf,
+ t_memory_reference *memory) {
+ struct XXElf* ELF = elfhandle->ELF;
+ const ElfXX_Rela* rel_start;
+ const ElfXX_Sym* relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->relaNmfSegmentSymbols;
+
+ for(rel_start = (ElfXX_Rela*)elftmp->relaNmfSegment; rel_start < (ElfXX_Rela*)elftmp->relaNmfSegmentEnd; rel_start++)
+ {
+ if((t_uint32)swapXword(rel_start->r_offset) == offsetInNmf)
+ {
+ int strtab_index = ELFXX_R_SYM(swapXword(rel_start->r_info));
+ int sectionIdx = (int)swapHalf(relaNmfSegmentSymbols[strtab_index].st_shndx);
+
+ memory->memory = ELF->sectionss[sectionIdx].meminfo;
+
+ if(memory->memory != NULL) {
+ memory->offset = (
+ ELF->sectionss[sectionIdx].offsetInSegment + // Offset in Segment
+ (t_uint32)swapXword(relaNmfSegmentSymbols[strtab_index].st_value) + // Offset in Elf Section
+ (t_uint32)swapXword(rel_start->r_addend)); // Addend
+
+ return CM_OK;
+ } else {
+ const char* symbol_name = &elftmp->relaNmfSegmentStrings[swapWord(relaNmfSegmentSymbols[strtab_index].st_name)];
+ ERROR("Symbol %s not found\n", symbol_name, 0, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ }
+ }
+ }
+
+ ERROR("Unknown relocation error\n", 0, 0, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c
new file mode 100644
index 00000000000..c6c316046b3
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+/*
+ *
+ */
+#include <cm/engine/elf/inc/mmdsp-loadmap.h>
+#include <cm/engine/elf/inc/mmdsp.h>
+#include <cm/engine/dsp/inc/semaphores_dsp.h>
+#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h>
+#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h>
+
+#include <cm/engine/power_mgt/inc/power.h>
+
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/memory/inc/domain.h>
+#include <cm/engine/component/inc/instance.h>
+#include <cm/engine/component/inc/component_type.h>
+#include <inc/nmf-limits.h>
+
+#define LOADMAP_SEMAPHORE_USE_NB 7
+
+static t_memory_handle headerHandle[NB_CORE_IDS] = {INVALID_MEMORY_HANDLE, };
+static struct LoadMapHdr *headerAddresses[NB_CORE_IDS] = {0, };
+static t_uint32 headerOffsets[NB_CORE_IDS] = {0, };
+static t_uint32 entryNumber[NB_CORE_IDS] = {0, };
+
+#undef myoffsetof
+#define myoffsetof(TYPE, MEMBER) ((unsigned int) &((TYPE *)0)->MEMBER)
+
+t_cm_error cm_DSPABI_AddLoadMap(
+ t_cm_domain_id domainId,
+ const char* templateName,
+ const char* localname,
+ t_memory_handle *memories,
+ void *componentHandle)
+{
+ t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId);
+ int count=0;
+ struct LoadMapItem* curItem = NULL;
+
+ if (headerHandle[coreId] == 0) /* Create loadmap header */
+ {
+ headerHandle[coreId] = cm_DM_Alloc(domainId, SDRAM_EXT16,
+ sizeof(struct LoadMapHdr)/2, CM_MM_ALIGN_2WORDS, TRUE);
+ if (headerHandle[coreId] == INVALID_MEMORY_HANDLE) {
+ ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap in cm_DSPABI_AddLoadMap()\n", 0, 0, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ headerAddresses[coreId] = (struct LoadMapHdr*)cm_DSP_GetHostLogicalAddress(headerHandle[coreId]);
+
+ headerAddresses[coreId]->nMagicNumber = LOADMAP_MAGIC_NUMBER;
+ headerAddresses[coreId]->nVersion = (LOADMAP_VERSION_MSB<<8)|(LOADMAP_VERSION_LSB);
+ headerAddresses[coreId]->nRevision = 0;
+ headerAddresses[coreId]->pFirstItem = 0;
+
+ //Register Header into XRAM:2
+ cm_DSP_GetDspAddress(headerHandle[coreId], &headerOffsets[coreId]);
+ cm_DSP_WriteXRamWord(coreId, 2, headerOffsets[coreId]);
+ }
+
+ // update Header nRevision field
+ headerAddresses[coreId]->nRevision++;
+
+ /*
+ * Build loadmap entry
+ */
+ {
+ t_memory_handle handle;
+ struct LoadMapItem* pItem;
+ t_uint32 dspentry;
+ unsigned char* pos;
+ t_uint32 fnlen, lnlen;
+ t_uint32 fnlenaligned, lnlenaligned;
+ t_uint32 address;
+ t_uint32 postStringLength;
+ int i;
+
+ postStringLength = cm_StringLength(".elf", 16);
+ fnlenaligned = fnlen = cm_StringLength(templateName, MAX_COMPONENT_FILE_PATH_LENGTH) + postStringLength + 2;
+ if((fnlenaligned % 2) != 0) fnlenaligned++;
+ lnlenaligned = lnlen = cm_StringLength(localname, MAX_TEMPLATE_NAME_LENGTH);
+ if((lnlenaligned % 2) != 0) lnlenaligned++;
+
+ // Allocate new loap map
+ handle = cm_DM_Alloc(domainId, SDRAM_EXT16,
+ sizeof(struct LoadMapItem)/2 + (1 + fnlenaligned/2) + (1 + lnlenaligned/2),
+ CM_MM_ALIGN_2WORDS, TRUE);
+ if (handle == INVALID_MEMORY_HANDLE) {
+ ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap entry in cm_DSPABI_AddLoadMap\n", 0, 0, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ pItem = (struct LoadMapItem*)cm_DSP_GetHostLogicalAddress(handle);
+ cm_DSP_GetDspAddress(handle, &dspentry);
+ count++;
+ entryNumber[coreId]++;
+
+ // Link this new loadmap with the previous one
+ if(headerAddresses[coreId]->pFirstItem == NULL)
+ headerAddresses[coreId]->pFirstItem = (struct LoadMapItem *)dspentry;
+ else
+ {
+ const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId);
+ t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2;
+ struct LoadMapItem* curItem, *prevItem = NULL;
+ t_uint32 curItemDspAdress;
+
+ if(
+ ((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) ||
+ ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr))
+ {
+ ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n",
+ headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0);
+
+ return CM_INVALID_DATA;
+ }
+ curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem;
+ curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address
+ count++;
+ while(curItem->pNextItem != NULL)
+ {
+ if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr))
+ {
+ if (prevItem == NULL)
+ ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n",
+ curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem,
+ 0, 0, 0, 0);
+ else
+ ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n",
+ curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem,
+ 0, 0, 0, 0);
+ return CM_INVALID_DATA;
+ }
+ curItemDspAdress = (t_uint32)curItem->pNextItem;
+ prevItem = curItem;
+ curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address
+ count++;
+ }
+ curItem->pNextItem = (struct LoadMapItem *)dspentry;
+ }
+
+ // DSP Address of the string at the end of the load map
+ pos = (unsigned char*)pItem + sizeof(struct LoadMapItem);
+
+ /*
+ * Set SolibFilename address information
+ * -> string = "./origfilename"
+ */
+ pItem->pSolibFilename = (char*)(dspentry + sizeof(struct LoadMapItem) / 2);
+ *(t_uint16*)pos = fnlen;
+ pos += 2;
+ *pos++ = '.';
+ *pos++ = '\\';
+ for(i = 0; i < fnlen - 2 - postStringLength; i++)
+ {
+ *pos++ = (templateName[i] == '.') ? '\\' : templateName[i];
+ }
+ *pos++ = '.';
+ *pos++ = 'e';
+ *pos++ = 'l';
+ *pos++ = 'f';
+ // add padding if needed
+ if ((t_uint32)pos & 1)
+ *pos++ = '\0';
+
+ /*
+ * Set Component Name address information
+ */
+ if (lnlen != 0)
+ {
+ pItem->pComponentName = (char*)(dspentry + sizeof(struct LoadMapItem) / 2 + 1 + fnlenaligned / 2);
+
+ *(t_uint16*)pos = lnlen;
+ pos += 2;
+ for(i = 0; i < lnlenaligned; i++)
+ {
+ // If not aligned null ending copied
+ *pos++ = localname[i];
+ }
+ }
+ else
+ {
+ pItem->pComponentName = 0;
+ }
+
+ /*
+ * Set PROG information
+ */
+ if(memories[CODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE)
+ address = 0;
+ else
+ cm_DSP_GetDspAddress(memories[CODE_MEMORY_INDEX], &address);
+ pItem->pAddrProg = (void*)address;
+
+ /*
+ * Set ERAMCODE information
+ */
+ if(memories[ECODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE)
+ address = 0;
+ else
+ cm_DSP_GetDspAddress(memories[ECODE_MEMORY_INDEX], &address);
+ pItem->pAddrEmbProg = (void*)address;
+
+ /*
+ * Set THIS information
+ */
+ if(memories[PRIVATE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) {
+ // Standard component
+ cm_DSP_GetDspAddress(memories[PRIVATE_DATA_MEMORY_INDEX], &address);
+ } else if(memories[SHARE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) {
+ // Singleton component where data are shared (simulate THIS with shared memory)
+ cm_DSP_GetDspAddress(memories[SHARE_DATA_MEMORY_INDEX], &address);
+ } else {
+ // Component without data (take unique identifier -> arbitrary take host component handle)
+ address = (t_uint32)componentHandle;
+ }
+ pItem->pThis = (void*)address;
+
+ /*
+ * Set ARM THIS information
+ */
+ pItem->pARMThis = componentHandle;
+
+ /*
+ * Set Link to null (end of list)
+ */
+ pItem->pNextItem = 0;
+
+ /*
+ * Set XROM information
+ */
+ if(memories[XROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE)
+ address = 0;
+ else
+ cm_DSP_GetDspAddress(memories[XROM_MEMORY_INDEX], &address);
+ pItem->pXROM = (void*)address;
+
+ /*
+ * Set YROM information
+ */
+ if(memories[YROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE)
+ address = 0;
+ else
+ cm_DSP_GetDspAddress(memories[YROM_MEMORY_INDEX], &address);
+ pItem->pYROM = (void*)address;
+
+ /*
+ * Set memory handle (not used externally)
+ */
+ ((t_component_instance *)componentHandle)->loadMapHandle = handle;
+ }
+
+ OSAL_mb();
+
+ if (count != entryNumber[coreId]) {
+ ERROR("AddLoadMap: corrumption, number of component differs: count=%d, expected %d (last item @ %p)\n",
+ count, entryNumber[coreId], curItem, 0, 0, 0);
+ return CM_INVALID_DATA;
+ }
+ return CM_OK;
+}
+
+t_cm_error cm_DSPABI_RemoveLoadMap(
+ t_cm_domain_id domainId,
+ const char* templateName,
+ t_memory_handle *memories,
+ const char* localname,
+ void *componentHandle)
+{
+ struct LoadMapItem **prevItemReference;
+ t_uint32 prevItemReferenceDspAddress, curItemDspAdress;
+ t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId);
+ const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId);
+ t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2;
+ struct LoadMapItem* curItem = NULL;
+
+ CM_ASSERT (headerHandle[coreId] != INVALID_MEMORY_HANDLE);
+
+ /* parse list until we find this */
+ prevItemReferenceDspAddress = 0x2; // DSP address of load map head pointer
+ prevItemReference = &headerAddresses[coreId]->pFirstItem;
+ curItemDspAdress = (t_uint32)*prevItemReference;
+ while(curItemDspAdress != 0x0)
+ {
+ if((curItemDspAdress < SDRAMMEM16_BASE_ADDR) || (curItemDspAdress > endSegmentAddr))
+ {
+ ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n",
+ prevItemReferenceDspAddress, prevItemReference, 0, 0, 0, 0);
+
+ /* free the entry anyway to avoid leakage */
+ cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE);
+
+ return CM_OK;
+ }
+
+ curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address
+
+ if(curItem->pARMThis == componentHandle)
+ {
+ // Remove component from loadmap
+
+ /* take local semaphore */
+ cm_DSP_SEM_Take(coreId,LOADMAP_SEMAPHORE_USE_NB);
+
+ /* remove element from list */
+ *prevItemReference = curItem->pNextItem;
+
+ /* update nRevision field in header */
+ headerAddresses[coreId]->nRevision++;
+
+ /* If this is the last item, deallocate !!! */
+ if(headerAddresses[coreId]->pFirstItem == NULL)
+ {
+ // Deallocate memory
+ cm_DM_Free(headerHandle[coreId], TRUE);
+ headerHandle[coreId] = INVALID_MEMORY_HANDLE;
+
+ //Register Header into XRAM:2
+ cm_DSP_WriteXRamWord(coreId, 2, 0);
+ }
+
+ /* deallocate memory */
+ cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE);
+
+ /* be sure memory is updated before releasing local semaphore */
+ OSAL_mb();
+
+ /* release local semaphore */
+ cm_DSP_SEM_Give(coreId,LOADMAP_SEMAPHORE_USE_NB);
+
+ entryNumber[coreId]--;
+
+ return CM_OK;
+ }
+
+ prevItemReferenceDspAddress = curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem);
+ prevItemReference = &curItem->pNextItem;
+ curItemDspAdress = (t_uint32)*prevItemReference;
+ };
+
+ ERROR("Memory corruption in MMDSP: component not in LoadMap %s\n", localname, 0, 0, 0, 0, 0);
+
+ /* free the entry anyway to avoid leakage */
+ cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE);
+
+ return CM_OK;
+}
+
+#if 0
+t_cm_error cm_DSPABI_CheckLoadMap_nolock(t_nmf_core_id coreId)
+{
+ int count=0;
+ static int dump = 5;
+ struct LoadMapItem* curItem = NULL;
+
+ if (!dump)
+ return CM_OK;
+ if (headerHandle[coreId] == 0) /* No load map yet */
+ return CM_OK;
+
+ {
+ // No entry in loadmap
+ if(headerAddresses[coreId]->pFirstItem == NULL)
+ return CM_OK;
+
+ {
+ const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId);
+ t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2;
+ struct LoadMapItem *prevItem=NULL;
+ t_uint32 curItemDspAdress;
+
+ if (((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) ||
+ ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr))
+ {
+ ERROR("CheckLoadMap: Memory corruption in MMDSP at first item: at data DSP address=%x or ARM address=%x\n",
+ headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0);
+ dump--;
+ return CM_INVALID_COMPONENT_HANDLE;
+ }
+ curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem;
+ curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]);
+ count++;
+ while(curItem->pNextItem != NULL)
+ {
+ if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr))
+ {
+ if (!prevItem)
+ ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n"
+ "Previous (first) component name %s<%s>\n",
+ count,
+ curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem,
+ (char*)(((t_component_instance *)&curItem->pARMThis)->pathname),
+ (char*)(((t_component_instance *)&curItem->pARMThis)->Template->name), 0);
+ else
+ ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n"
+ "Previous valid component name %s<%s>",
+ count,
+ curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem,
+ (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname),
+ (char*)(((t_component_instance *)&prevItem->pARMThis)->Template->name), 0);
+ dump--;
+ return CM_INVALID_COMPONENT_HANDLE;
+ }
+ curItemDspAdress = (t_uint32)curItem->pNextItem;
+ prevItem = curItem;
+ curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address
+ count++;
+ }
+ }
+
+ }
+
+ if (count != entryNumber[coreId]) {
+ ERROR("CheckLoadMap: number of component differs: count=%d, expected %d (last item @ %p)\n", count, entryNumber[coreId],
+ curItem, 0, 0, 0);
+ dump--;
+ return CM_INVALID_COMPONENT_HANDLE;
+ }
+ return CM_OK;
+}
+
+t_cm_error cm_DSPABI_CheckLoadMap(t_nmf_core_id coreId)
+{
+ t_cm_error error;
+ OSAL_LOCK_API();
+ error = cm_DSPABI_CheckLoadMap_nolock(coreId);
+ OSAL_UNLOCK_API();
+ return error;
+}
+#endif
diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c
new file mode 100644
index 00000000000..93d910a5ed6
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c
@@ -0,0 +1,6 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+#include <cm/engine/elf/inc/mpcal.h>