summaryrefslogtreecommitdiffstats
path: root/main/common/start.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/common/start.c')
-rw-r--r--main/common/start.c496
1 files changed, 496 insertions, 0 deletions
diff --git a/main/common/start.c b/main/common/start.c
new file mode 100644
index 0000000..18919a2
--- /dev/null
+++ b/main/common/start.c
@@ -0,0 +1,496 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2013 Alcatel-Lucent
+ *
+ * Alcatel Lucent licenses this file to You under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. A copy of the License is contained the
+ * file LICENSE at the top level of this repository.
+ * You may also obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************
+ *
+ * start.c:
+ *
+ * This is typically the first 'C' code executed by the processor after a
+ * reset.
+ *
+ * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com)
+ *
+ */
+#include "config.h"
+#include "cpu.h"
+#include "cpuio.h"
+#include "stddefs.h"
+#include "genlib.h"
+#include "devices.h"
+#include "ether.h"
+#include "warmstart.h"
+#include "monlib.h"
+#include "monflags.h"
+#include "boardinfo.h"
+#include "cli.h"
+#include "tfsprivate.h"
+#include "fbi.h"
+
+#ifdef PRE_COMMANDLOOP_HOOK
+extern void PRE_COMMANDLOOP_HOOK();
+#endif
+
+#ifndef EXCEPTION_HEADING
+#define EXCEPTION_HEADING "EXCEPTION"
+#endif
+
+extern void vinit(void);
+extern int addcommand(struct monCommand *cmdlist, char *cmdlvl);
+
+/* StateOfMonitor:
+ * The StateOfMonitor variable is used throughout the code to determine
+ * how the monitor started up. In general, the three most common
+ * startup types are: INITIALIZE, APP_EXIT and EXCEPTION.
+ */
+int StateOfMonitor;
+
+/* MonStack:
+ * The monitor's stack is declared within the monitor's own .bss space.
+ * This keeps the memory map simple, the only thing that needs to be
+ * accounted for is that in the bss init loop, this section should not
+ * be initialized. MONSTACKSIZE must be defined in config.h.
+ */
+ulong MonStack[MONSTACKSIZE/4];
+
+/* APPLICATION_RAMSTART:
+ * Loaded with the address after which the application can be loaded.
+ */
+ulong APPLICATION_RAMSTART;
+
+/* BOOTROM_BASE:
+ * Loaded with the address considered to be the base address at which
+ * the monitor is burned into flash.
+ */
+ulong BOOTROM_BASE;
+
+/* LoopsPerMillisecond:
+ * Loaded with a count (established in config.h) that is an estimation of
+ * one second of elapsed time. It is NOT an accurate value, but serves the
+ * purpose of providing a hardware-independent mechanism for establishing
+ * a reasonable estimation of one second's worth of elapsed time.
+ */
+ulong LoopsPerMillisecond;
+
+/* init0():
+ * The code in this function was originally part of start(). It has been
+ * moved out so that this portion of the initialization can be re-used by
+ * AppWarmStart(). See notes in AppWarmStart() for more details on this.
+ */
+void
+init0(void)
+{
+ /* Store the base address of memory that is used by application.
+ * Start it off on the next 4K boundary after the end of monitor ram.
+ * Usually APPRAMBASE and BOOTROMBASE can be retrieved from bss_end and
+ * boot_base; but they can be overridden with values specified in the
+ * target-specific config.h file.
+ */
+#ifdef APPRAMBASE_OVERRIDE
+ APPLICATION_RAMSTART = APPRAMBASE_OVERRIDE;
+#else
+ APPLICATION_RAMSTART = (((ulong)&bss_end) | 0xfff) + 1;
+#endif
+
+#ifdef BOOTROMBASE_OVERRIDE
+ BOOTROM_BASE = BOOTROMBASE_OVERRIDE;
+#else
+ BOOTROM_BASE = (ulong)&boot_base;
+#endif
+
+ /* Load bottom of stack with 0xdeaddead to be used by stkchk().
+ */
+ MonStack[0] = 0xdeaddead;
+
+ /* Set up default loops-per-millisecond count.
+ */
+ LoopsPerMillisecond = LOOPS_PER_SECOND/1000;
+
+ /* Clear any user-installed command list.
+ */
+ addcommand(0,0);
+}
+
+/* init1():
+ * This is the first level of initialization (aside from the most fundamental
+ * stuff that must be done in reset.s) that is done after the system resets.
+ */
+void
+init1(void)
+{
+ initCPUio(); /* Configure all chip-selects, parallel IO
+ * direction registers, etc... This may have
+ * been done already in reset.s
+ */
+ vinit(); /* Initialize the CPU's vector table. */
+ InitRemoteIO(); /* Initialize all application-settable IO functions */
+
+ if (ConsoleBaudRate == 0)
+ ConsoleBaudRate = DEFAULT_BAUD_RATE;
+
+ devInit(ConsoleBaudRate);
+
+}
+
+/* init2():
+ */
+void
+init2(void)
+{
+#if INCLUDE_FLASH | INCLUDE_TFS
+ int rc = 0;
+#endif
+
+#if INCLUDE_FBI
+ if (StateOfMonitor == INITIALIZE)
+ fbdev_init(); /* Initialize the frame-buffer device */
+#endif
+
+#if INCLUDE_FLASH
+ if (StateOfMonitor == INITIALIZE)
+ rc = FlashInit(); /* Init flashop data structures and (possibly) */
+ /* the relocatable functions. This MUST be */
+#endif /* done prior to turning on cache!!! */
+
+ cacheInit(); /* Initialize cache. */
+
+#if INCLUDE_ETHERNET
+ enreset(); /* Clear the ethernet interface. */
+#endif
+
+#if INCLUDE_TFS
+ if (rc != -1) /* Start up TFS as long as flash */
+ tfsstartup(); /* initialization didn't fail. */
+#endif
+}
+
+/* init3():
+ * As each target boots up, it calls init1() and init2() to do multiple
+ * phases of hardware initialization. This third initialization phase
+ * is always common to all targets...
+ * It is possible that this is being called by AppWarmStart(). In this
+ * case, the user can specify which portions of the monitor code are
+ * to be initialized by specifying them in the startmode mask.
+ */
+static void
+_init3(ulong startmode)
+{
+ char *baud;
+
+#if INCLUDE_LINEEDIT
+ /* Initialize command line history table. */
+ historyinit();
+#endif
+
+#if INCLUDE_SHELLVARS
+ /* Init shell variable table. */
+ ShellVarInit();
+#endif
+
+#if INCLUDE_USRLVL
+ /* Set user level to its max, then allow monrc file to adjust it. */
+ initUsrLvl(MAXUSRLEVEL);
+#endif
+
+#if INCLUDE_BOARDINFO
+ /* Check for board-specific-information in some otherwise unused
+ * sector. Also, establish shell variables from this information
+ * based on the content of the boardinfo structure.
+ * Note that the second half of the board-specific information setup
+ * (the call to BoardInfoEnvInit()) must be done AFTER ShellVarInit()
+ * because shell variables are established here.
+ */
+ if (startmode & WARMSTART_BOARDINFO) {
+ BoardInfoInit();
+ BoardInfoEnvInit();
+ }
+#endif
+
+#ifdef MONCOMPTR
+ /* If MONCOMPTR is defined, then verify that the definition matches
+ * the location of the actual moncomptr value. The definition in
+ * config.h is provided so that outside applications can include that
+ * header file so that the value passed into monConnect() is defined
+ * formally. The REAL value of moncomptr is based on the location of
+ * the pointer in monitor memory space, determined only after the final
+ * link has been done. As a result, this check is used to simply verify
+ * that the definition matches the actual value.
+ */
+ {
+ if (MONCOMPTR != (ulong)&moncomptr)
+ printf("\nMONCOMPTR WARNING: runtime != definition\n");
+ }
+#endif
+
+#if INCLUDE_TFS
+ /* After basic initialization, if the monitor's run-control file
+ * exists, run it prior to EthernetStartup() so that the
+ * MAC/IP addresses can be configured based on shell variables
+ * that would be loaded by the rc file.
+ */
+ if (startmode & WARMSTART_RUNMONRC)
+ tfsrunrcfile();
+#endif
+
+ /* After MONRC is run, establish monitor flags...
+ */
+ InitMonitorFlags();
+
+ /* We've run the monrc file at this point, so check for the
+ * presence of the CONSOLEBAUD shell variable. If it's set,
+ * then use the value to re-establish the console baud rate.
+ * If it isn't set, then establish the CONSOLEBAUD shell variable
+ * using the default, pre-configured baud rate.
+ */
+ baud = getenv("CONSOLEBAUD");
+ if (baud)
+ ChangeConsoleBaudrate(atoi(baud));
+ ConsoleBaudEnvSet();
+
+#if INCLUDE_ETHERNET
+#if INCLUDE_STOREMAC
+ storeMac(0);
+#endif
+ if (startmode & WARMSTART_IOINIT)
+ EthernetStartup(0,1);
+#endif
+
+ /* Now that all has been initialized, display the monitor header. */
+#ifndef NO_UMON_STARTUP_HDR
+ if (startmode & WARMSTART_MONHEADER) {
+ if (!MFLAGS_NOMONHEADER())
+ monHeader(1);
+ }
+#endif
+
+#if INCLUDE_FBI
+ if (StateOfMonitor == INITIALIZE)
+ fbi_splash();
+#endif
+
+#if INCLUDE_TFS
+ if (startmode & WARMSTART_TFSAUTOBOOT)
+ tfsrunboot();
+#endif
+}
+
+void
+init3(void)
+{
+ _init3(WARMSTART_ALL);
+}
+
+/* umonBssInit():
+ * All of the monitor-owned ram is within it's bss space as defined
+ * by the locations of bss_start and bss_end in the memory map
+ * definition file. This includes the the monitor's stack and
+ * heap. To support a generic, C-based BSS initialzation loop,
+ * this loop must skip over the space allocated to the stack because
+ * the stack is likely to be in use during this loop...
+ */
+void
+umonBssInit(void)
+{
+ int *tmp;
+ volatile ulong *bssptr;
+
+ tmp = &bss_start;
+ bssptr = (ulong *)tmp;
+ while(bssptr < MonStack)
+ *bssptr++ = 0;
+ bssptr = (ulong *)MonStack+(MONSTACKSIZE/4);
+ tmp = &bss_end;
+ while(bssptr < (ulong *)tmp)
+ *bssptr++ = 0;
+}
+
+/* AppWarmStart():
+ * This function is provided to allow the application to partially
+ * restart the monitor. It supports the situation where an application
+ * run but the monitor has not already been initialized. This would be
+ * the case if some type of debugger (JTAG or BDM probably) was attached
+ * to the target and it was used to download and run the application.
+ * If this type of debug connection does not support the ability to run
+ * after the monitor runs, then the application must be able to somehow
+ * get the monitor initialized without having it go through a complete
+ * warmstart.
+ * This will only run through the stack space provided by the application.
+ */
+void
+AppWarmStart(ulong mask)
+{
+ /* First initialize monitor bss space (skipping over MonStack[]): */
+ if (mask & WARMSTART_BSSINIT)
+ umonBssInit();
+
+ StateOfMonitor = INITIALIZE;
+
+ /* Initialize some of the real fundamental stuff regardless of
+ * the incoming mask.
+ */
+ init0();
+
+ /* Subset of init1(): */
+ if (mask & WARMSTART_IOINIT) {
+ initCPUio();
+ InitRemoteIO();
+ if (ConsoleBaudRate == 0)
+ ConsoleBaudRate = DEFAULT_BAUD_RATE;
+ devInit(ConsoleBaudRate);
+ }
+ init2();
+ _init3(mask);
+}
+
+/* start():
+ * Called at the end of reset.s as the first C function after processor
+ * bootup. It is passed a state that is used to determine whether or not
+ * the CPU is restarting as a result of a warmstart or a coldstart. If
+ * the restart is a coldstart, then state will be INITIALIZE. if the
+ * restart is a warmstart, then there are a few typical values of state,
+ * the most common of which are APP_EXIT and EXCEPTION.
+ *
+ * The bss_start and bss_end variables are usually defined in the
+ * target-specific linker memory-map definition file. They symbolically
+ * identify the beginning and end of the .bss section. Many compilers
+ * support intrinsic tags for this; however, since it is apparently not
+ * consistent from one toolset to the next; I chose to make up my own
+ * tags so that this file never changes from one toolset to the next.
+ *
+ * The FORCE_BSS_INIT definition can be established in the target-specific
+ * config.h file to force .bss space initialization regardless of warm/cold
+ * start.
+ */
+void
+start(int state)
+{
+ char buf[48];
+
+#ifdef FORCE_BSS_INIT
+ state = INITIALIZE;
+#endif
+
+ /* Based on the incoming value of 'state' we may or may not initialize
+ * monitor-owned ram. Ideally, we only want to initialize
+ * monitor-owned ram when 'state' is INITIALIZE (power-up or reset);
+ * however, to support the case where the incoming state variable may
+ * be corrupted, we also initialize monitor-owned ram when 'state'
+ * is anything unexpected...
+ */
+ switch(state) {
+ case EXCEPTION:
+ case APP_EXIT:
+ break;
+ case INITIALIZE:
+ default:
+ umonBssInit();
+ break;
+ }
+
+ /* Now that the BSS clear loop has been done, we can copy the
+ * value of state (either a register or on stack) to the global
+ * variable (in BSS) StateOfMonitor...
+ */
+ StateOfMonitor = state;
+
+ /* Step through different phases of startup...
+ */
+ init0();
+ init1();
+ init2();
+
+ /* Depending on the type of startup, alert the console and do
+ * further initialization as needed...
+ */
+ switch(StateOfMonitor) {
+ case INITIALIZE:
+ reginit();
+ init3();
+ break;
+ case APP_EXIT:
+ EthernetStartup(0,0);
+ if (!MFLAGS_NOEXITSTATUS()) {
+ printf("\nApplication Exit Status: %d (0x%x)\n",
+ AppExitStatus,AppExitStatus);
+ }
+ break;
+ case EXCEPTION:
+ EthernetStartup(0,0);
+ printf("\n%s: '%s'\n",EXCEPTION_HEADING,
+ ExceptionType2String(ExceptionType));
+ printf(" Occurred near 0x%lx",ExceptionAddr);
+ if (AddrToSym(-1,ExceptionAddr,buf,0))
+ printf(" (within %s)",buf);
+ printf("\n\n");
+ exceptionAutoRestart(INITIALIZE);
+ break;
+ default:
+ printf("Unexpected monitor state: 0x%x (sp @ 0x%x)\n",
+ StateOfMonitor, buf);
+ /* To attempt to recover from the bad state, just do
+ * what INITIALIZE would do...
+ */
+ reginit();
+ init3();
+ break;
+ }
+
+#ifdef LOCK_FLASH_PROTECT_RANGE
+ /* Issue the command that will cause the range of sectors
+ * designated by FLASH_PROTECT_RANGE to be locked. This only
+ * works if the flash device is capable of being locked.
+ */
+ sprintf(buf,"flash lock %s",FLASH_PROTECT_RANGE);
+ docommand(buf,0);
+#endif
+
+#ifdef PRE_COMMANDLOOP_HOOK
+ PRE_COMMANDLOOP_HOOK();
+#endif
+
+ /* Enter the endless loop of command processing: */
+ CommandLoop();
+
+ printf("ERROR: CommandLoop() returned\n");
+ monrestart(INITIALIZE);
+}
+
+/* __eabi():
+ * Called intrinsically by main for some PowerPc builds.
+ * I'm not sure what the purpose of it is, but EABI is Embedded Application
+ * Binary Interface, and is documented on Motorola's web site at
+ * http://www.mcu.motsps.com/lit/manuals/eabispec.html#536421
+ */
+void
+__eabi(void)
+{
+}
+
+/* __main() or __gccmain(): called intrinsically by main. One or the other
+ * is typically used to run constructors and destructors for C++. If this
+ * function is not created here, then the compiler will automatically create
+ * one and with it, will come other unnecessary baggage.
+ */
+void
+__main(void)
+{
+}
+
+void
+__gccmain(void)
+{
+}