]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/powerpc/adder/v2_0/src/redboot_linux_exec.c
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / packages / hal / powerpc / adder / v2_0 / src / redboot_linux_exec.c
1 //==========================================================================
2 //
3 //      redboot_linux_boot.c
4 //
5 //      RedBoot command to boot Linux
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //####OTHERCOPYRIGHTBEGIN####
42 //
43 //  The structure definitions below are taken from include/ppc/platforms/am860.h in
44 //  the Linux kernel, Copyright (c) 2002 Gary Thomas, Copyright (c) 1997 Dan Malek. 
45 //  Their presence here is for the express purpose of communication with the Linux 
46 //  kernel being booted and is considered 'fair use' by the original author and
47 //  are included with their permission.
48 //
49 //####OTHERCOPYRIGHTEND####
50 //==========================================================================
51 //#####DESCRIPTIONBEGIN####
52 //
53 // Author(s):    msalter
54 // Contributors: gthomas,msalter
55 // Date:         2002-01-14
56 // Purpose:      
57 // Description:  
58 //              
59 // This code is part of RedBoot (tm).
60 //
61 //####DESCRIPTIONEND####
62 //
63 //==========================================================================
64
65 #include <redboot.h>
66 #include <pkgconf/hal_powerpc_quicc.h>
67
68 #include <cyg/hal/hal_arch.h>
69 #include <cyg/hal/hal_if.h>
70 #include <cyg/hal/hal_intr.h>
71 #include <cyg/hal/hal_cache.h>
72
73 #ifdef CYGPKG_REDBOOT_NETWORKING
74 #include <net/net.h>
75 #endif
76
77 #ifdef CYGSEM_REDBOOT_HAL_LINUX_BOOT
78
79 #include CYGHWR_MEMORY_LAYOUT_H
80
81 //=========================================================================
82
83 // Exported CLI function(s)
84 static void do_exec(int argc, char *argv[]);
85 RedBoot_cmd("exec", 
86             "Execute a Linux image - with MMU off", 
87             "[-w timeout]\n"
88             "        [-c \"kernel command line\"] [<entry_point>]",
89             do_exec
90     );
91
92 //=========================================================================
93 // Imported from Linux kernel include/asm-ppc/am860.h
94 //   Copyright (c) 2002 Gary Thomas (gary@chez-thomas.org)
95 //   Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
96 //   Used with permission of author(s).
97
98
99 /* A Board Information structure that is given to a program when
100  * RedBoot starts it up.
101  */
102 typedef struct bd_info {
103         unsigned int    bi_tag;         /* Should be 0x42444944 "BDID" */
104         unsigned int    bi_size;        /* Size of this structure */
105         unsigned int    bi_revision;    /* revision of this structure */
106         unsigned int    bi_bdate;       /* EPPCbug date, i.e. 0x11061997 */
107         unsigned int    bi_memstart;    /* Memory start address */
108         unsigned int    bi_memsize;     /* Memory (end) size in bytes */
109         unsigned int    bi_intfreq;     /* Internal Freq, in Hz */
110         unsigned int    bi_busfreq;     /* Bus Freq, in Hz */
111         unsigned int    bi_clun;        /* Boot device controller */
112         unsigned int    bi_dlun;        /* Boot device logical dev */
113         unsigned char   bi_enetaddr[6];
114         unsigned int    bi_baudrate;
115         unsigned char   *bi_cmdline;
116 } bd_t;
117
118 //
119 // Execute a Linux kernel - this is a RedBoot CLI command
120 //
121 static void 
122 do_exec(int argc, char *argv[])
123 {
124     unsigned long entry;
125     bool wait_time_set, cmd_line_set;
126     int  wait_time;
127     char *cmd_line;
128     char *cline;
129     struct option_info opts[2];
130     hal_virtual_comm_table_t *__chan;
131     int baud_rate;
132
133     bd_t *board_info;
134     CYG_INTERRUPT_STATE oldints;
135     unsigned long sp = CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE;
136     
137     init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
138               (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
139     init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
140               (void **)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
141     entry = entry_address;  // Default from last 'load' operation
142     if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, 
143                    "[physical] starting address")) {
144         return;
145     }
146
147     // Determine baud rate on current console
148     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
149     baud_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
150     if (baud_rate <= 0) {
151         baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
152     }
153
154     // Make a little space at the top of the stack, and align to
155     // 64-bit boundary.
156     sp = (sp-128) & ~7;  // The Linux boot code uses this space for FIFOs
157     
158     // Copy the commandline onto the stack, and set the SP to just below it.
159     if (cmd_line_set) {
160         int len,i;
161
162         // get length of string
163         for( len = 0; cmd_line[len] != '\0'; len++ );
164
165         // decrement sp by length of string and align to
166         // word boundary.
167         sp = (sp-(len+1)) & ~3;
168
169         // assign this SP value to command line start
170         cline = (char *)sp;
171
172         // copy command line over.
173         for( i = 0; i < len; i++ )
174             cline[i] = cmd_line[i];
175         cline[len] = '\0';
176
177     } else {
178         cline = (char *)NULL;
179     }
180     
181     // Set up parameter struct at top of stack
182     sp = sp-sizeof(bd_t);
183     board_info = (bd_t *)sp;
184     memset(board_info, sizeof(*board_info), 0);
185     
186     board_info->bi_tag          = 0x42444944;
187     board_info->bi_size         = sizeof(board_info);
188     board_info->bi_revision     = 1;
189     board_info->bi_bdate        = 0x06012002;
190     board_info->bi_memstart     = CYGMEM_REGION_ram;
191     board_info->bi_memsize      = CYGMEM_REGION_ram_SIZE;
192     board_info->bi_intfreq      = CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000;
193     board_info->bi_busfreq      = 66*1000000;
194     board_info->bi_clun         = 0;  // ????
195     board_info->bi_dlun         = 0;  // ????
196     board_info->bi_baudrate     = baud_rate;
197     board_info->bi_cmdline      = cline;
198 #ifdef CYGPKG_REDBOOT_NETWORKING
199     memcpy(board_info->bi_enetaddr, __local_enet_addr, sizeof(enet_addr_t));
200 #endif
201
202     // adjust SP to 64 bit boundary, and leave a little space
203     // between it and the commandline for PowerPC calling
204     // conventions.
205         
206     sp = (sp-32)&~7;
207
208     if (wait_time_set) {
209         int script_timeout_ms = wait_time * 1000;
210 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
211         unsigned char *hold_script = script;
212         script = (unsigned char *)0;
213 #endif
214         diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
215                     (void *)entry, wait_time);
216         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
217             int res;
218             char line[80];
219             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
220             if (res == _GETS_CTRLC) {
221 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
222                 script = hold_script;  // Re-enable script
223 #endif
224                 return;
225             }
226             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
227         }
228     }
229
230     // Disable interrupts
231     HAL_DISABLE_INTERRUPTS(oldints);
232
233     // Put the caches to sleep.
234     HAL_DCACHE_SYNC();
235     HAL_ICACHE_DISABLE();
236     HAL_DCACHE_DISABLE();
237     HAL_DCACHE_SYNC();
238     HAL_ICACHE_INVALIDATE_ALL();
239     HAL_DCACHE_INVALIDATE_ALL();
240
241 //    diag_printf("entry %08x, sp %08x, info %08x, cmd line %08x, baud %d\n",
242 //              entry, sp, board_info, cline, baud_rate);
243 //    breakpoint();
244     
245     // Call into Linux
246     __asm__ volatile (        
247                        // Start by disabling MMU - the mappings are
248                        // 1-1 so this should not cause any problems
249                        "mfmsr   3\n"
250                        "li      4,0xFFFFFFCF\n"
251                        "and     3,3,4\n"
252                        "sync\n"
253                        "mtmsr   3\n"
254                        "sync\n"
255
256                        // Now set up parameters to jump into linux
257
258                        "mtlr    %0\n"           // set entry address in LR
259                        "mr      1,%1\n"         // set stack pointer
260                        "mr      3,%2\n"         // set board info in R3
261                        "mr      4,%3\n"         // set command line in R4
262                        "blr          \n"        // jump into linux
263                        :
264                        : "r"(entry),"r"(sp),"r"(board_info),"r"(cline)
265                        : "r3", "r4"
266                      
267                      );
268 }
269
270 #endif // CYGSEM_REDBOOT_HAL_LINUX_BOOT
271
272 //=========================================================================
273 // EOF redboot_linux_exec.c