sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\nkernsmp\arm\nk_entry.cia sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include "nk_priv.h" sl@0: sl@0: #include "entry.h" sl@0: sl@0: #ifndef EKA2_ENTRY_POINT_VERSION_IDENTIFIER sl@0: #define EKA2_ENTRY_POINT_VERSION_IDENTIFIER \ sl@0: asm("tst pc, #%a0" : : "i" ((TInt)0) ) sl@0: #endif sl@0: sl@0: extern "C" { sl@0: sl@0: extern void HwInit0(); sl@0: extern void KernelMain(); sl@0: extern TLinAddr RomHeaderAddress; sl@0: extern TLinAddr SuperPageAddress; sl@0: sl@0: /* sl@0: * The main startup program sl@0: * aRomHeader is address of ROM header passed in by bootstrap sl@0: * aSuperPage is address of super page passed in by bootstrap sl@0: * sl@0: * *** NOTE *** sl@0: * This is written in assembler in order that nk_exe.lib can be built entirely sl@0: * from one source file. This is necessary to ensure that the vector table above sl@0: * appears at the very beginning of the ekern.exe code section. sl@0: * ************ sl@0: */ sl@0: #if defined(__GCC32__) sl@0: GLDEF_C __NAKED__ void _E32Startup(TLinAddr /*aRomHeader*/, TLinAddr /*aSuperPage*/) sl@0: { sl@0: EKA2_ENTRY_POINT_VERSION_IDENTIFIER; // DUMMY INSTRUCTION TO INDICATE EKA2 ENTRY POINT sl@0: asm("ldr r2, __RomHeaderAddress "); sl@0: asm("b 1f "); // branch over space for unique ID sl@0: sl@0: asm(".word 0 "); // loader will replace with code seg unique ID sl@0: // for RAM-loaded code segment sl@0: // MUST BE AT OFFSET 12 FROM ENTRY POINT sl@0: sl@0: asm("1: "); sl@0: asm("ldr r3, __SuperPage "); sl@0: asm("str r0, [r2] "); sl@0: asm("str r1, [r3] "); sl@0: sl@0: #ifdef __CPU_HAS_CP15_THREAD_ID_REG sl@0: asm("mov r0, #0 "); sl@0: SET_RWNO_TID(,r0); // initialise SubScheduler() pointer to 0 sl@0: SET_RWRO_TID(,r0); sl@0: SET_RWRW_TID(,r0); sl@0: #endif sl@0: sl@0: asm("bl HwInit0 "); sl@0: sl@0: asm("ldr r4, __CtorList "); sl@0: sl@0: asm("1: "); sl@0: asm("ldr r0, [r4, #4]! "); sl@0: asm("adr lr, 1b "); sl@0: asm("cmp r0, #0 "); sl@0: asm("mrs r1, cpsr "); sl@0: ASM_DEBUG2(GlobalCtor,r0,r1); sl@0: __JUMP(ne,r0); sl@0: sl@0: asm("b KernelMain "); sl@0: sl@0: asm("__RomHeaderAddress: "); sl@0: asm(".word RomHeaderAddress "); sl@0: asm("__SuperPage: "); sl@0: asm(".word SuperPageAddress "); sl@0: asm("__CtorList: "); sl@0: asm(".word __CTOR_LIST__ "); sl@0: } sl@0: #elif defined(__ARMCC__) sl@0: void __DLL_Export_Table__(void); sl@0: void __cpp_initialize__aeabi_(); sl@0: sl@0: // The compiler generates calls to this when it reckons a top-level construction sl@0: // needs destruction. But the kernel never will need this so, define it as a nop sl@0: void __record_needed_destruction (void * d){} sl@0: // 2.1 calls __aeabi_atexit passing __dso_handle. This can be a dummy (i.e. just a label) sl@0: sl@0: __asm void __dso_handle(void) {} sl@0: void __aeabi_atexit(void *object, void (*dtor)(void *), void *handle){} sl@0: sl@0: void _E32Startup_Body(TLinAddr aRomHeader, TLinAddr aSuperPage); sl@0: sl@0: __NAKED__ void _E32Startup(TLinAddr aRomHeader, TLinAddr aSuperPage) sl@0: { sl@0: EKA2_ENTRY_POINT_VERSION_IDENTIFIER; // DUMMY INSTRUCTION TO INDICATE EKA2 ENTRY POINT sl@0: asm("b 1f "); sl@0: asm(".word 0 "); // padding sl@0: sl@0: asm(".word 0 "); // loader will replace with code seg unique ID sl@0: // for RAM-loaded code segment sl@0: // MUST BE AT OFFSET 12 FROM ENTRY POINT sl@0: asm("1: "); sl@0: #ifdef __CPU_HAS_CP15_THREAD_ID_REG sl@0: asm("mov r12, #0 "); sl@0: SET_RWNO_TID(,r12); // initialise SubScheduler() pointer to 0 sl@0: SET_RWRO_TID(,r12); sl@0: SET_RWRW_TID(,r12); sl@0: #endif sl@0: asm("mov r12, #0 "); sl@0: SET_RWNO_TID(,r12); // initialise SubScheduler() pointer to 0 sl@0: asm("b _E32Startup_Body "); sl@0: sl@0: } sl@0: sl@0: GLDEF_C void _E32Startup_Body(TLinAddr aRomHeader, TLinAddr aSuperPage) sl@0: { sl@0: RomHeaderAddress = aRomHeader; sl@0: SuperPageAddress = aSuperPage; sl@0: HwInit0(); sl@0: sl@0: // RVCT specific initialization sl@0: sl@0: // Make sure we get an export table sl@0: __DLL_Export_Table__(); sl@0: sl@0: // Initialise static data sl@0: __cpp_initialize__aeabi_(); sl@0: sl@0: KernelMain(); sl@0: } sl@0: #else sl@0: #error Not supported sl@0: #endif sl@0: sl@0: } sl@0: