]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/powerpc/csb281/v2_0/src/redboot_linux_exec.c
Initial revision
[karo-tx-redboot.git] / packages / hal / powerpc / csb281 / 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 <cyg/hal/hal_arch.h>
67 #include <cyg/hal/hal_if.h>
68 #include <cyg/hal/hal_intr.h>
69 #include <cyg/hal/hal_cache.h>
70
71 #ifdef CYGPKG_REDBOOT_NETWORKING
72 #include <net/net.h>
73 #endif
74
75 #ifdef CYGSEM_REDBOOT_HAL_LINUX_BOOT
76
77 #include CYGHWR_MEMORY_LAYOUT_H
78
79 //=========================================================================
80
81 // Exported CLI function(s)
82 static void do_exec(int argc, char *argv[]);
83 RedBoot_cmd("exec", 
84             "Execute a Linux image - with MMU off", 
85             "[-w timeout]\n"
86             "        [-c \"kernel command line\"] [<entry_point>]",
87             do_exec
88     );
89
90 //=========================================================================
91 // Imported from Linux kernel include/asm-ppc/am860.h
92 //   Copyright (c) 2002 Gary Thomas (gary@chez-thomas.org)
93 //   Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
94 //   Used with permission of author(s).
95
96
97 /* A Board Information structure that is given to a program when
98  * RedBoot starts it up.
99  */
100 typedef struct bd_info {
101         unsigned int    bi_tag;         /* Should be 0x42444944 "BDID" */
102         unsigned int    bi_size;        /* Size of this structure */
103         unsigned int    bi_revision;    /* revision of this structure */
104         unsigned int    bi_bdate;       /* EPPCbug date, i.e. 0x11061997 */
105         unsigned int    bi_memstart;    /* Memory start address */
106         unsigned int    bi_memsize;     /* Memory (end) size in bytes */
107         unsigned int    bi_intfreq;     /* Internal Freq, in Hz */
108         unsigned int    bi_busfreq;     /* Bus Freq, in Hz */
109         unsigned int    bi_clun;        /* Boot device controller */
110         unsigned int    bi_dlun;        /* Boot device logical dev */
111         unsigned char   bi_enetaddr[6];
112         unsigned int    bi_baudrate;
113         unsigned char   *bi_cmdline;
114 } bd_t;
115
116 //
117 // Execute a Linux kernel - this is a RedBoot CLI command
118 //
119 static void 
120 do_exec(int argc, char *argv[])
121 {
122     unsigned long entry;
123     bool wait_time_set, cmd_line_set;
124     int  wait_time;
125     char *cmd_line;
126     char *cline;
127     struct option_info opts[2];
128     hal_virtual_comm_table_t *__chan;
129     int baud_rate;
130
131     bd_t *board_info;
132     CYG_INTERRUPT_STATE oldints;
133     unsigned long sp = CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE;
134     
135     init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
136               (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
137     init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
138               (void **)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
139     entry = entry_address;  // Default from last 'load' operation
140     if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, 
141                    "[physical] starting address")) {
142         return;
143     }
144
145     // Determine baud rate on current console
146     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
147     baud_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
148     if (baud_rate <= 0) {
149         baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
150     }
151
152     // Make a little space at the top of the stack, and align to
153     // 64-bit boundary.
154     sp = (sp-128) & ~7;  // The Linux boot code uses this space for FIFOs
155     
156     // Copy the commandline onto the stack, and set the SP to just below it.
157     if (cmd_line_set) {
158         int len,i;
159
160         // get length of string
161         for( len = 0; cmd_line[len] != '\0'; len++ );
162
163         // decrement sp by length of string and align to
164         // word boundary.
165         sp = (sp-(len+1)) & ~3;
166
167         // assign this SP value to command line start
168         cline = (char *)sp;
169
170         // copy command line over.
171         for( i = 0; i < len; i++ )
172             cline[i] = cmd_line[i];
173         cline[len] = '\0';
174
175     } else {
176         cline = (char *)NULL;
177     }
178     
179     // Set up parameter struct at top of stack
180     sp = sp-sizeof(bd_t);
181     board_info = (bd_t *)sp;
182     memset(board_info, sizeof(*board_info), 0);
183     
184     board_info->bi_tag          = 0x42444944;
185     board_info->bi_size         = sizeof(board_info);
186     board_info->bi_revision     = 1;
187     board_info->bi_bdate        = 0x06012002;
188     board_info->bi_memstart     = CYGMEM_REGION_ram;
189     board_info->bi_memsize      = CYGMEM_REGION_ram_SIZE;
190     board_info->bi_intfreq      = CYGHWR_HAL_POWERPC_CPU_SPEED*1000000;
191     board_info->bi_busfreq      = CYGHWR_HAL_POWERPC_MEM_SPEED*1000000;
192     board_info->bi_clun         = 0;  // ????
193     board_info->bi_dlun         = 0;  // ????
194     board_info->bi_baudrate     = baud_rate;
195     board_info->bi_cmdline      = cline;
196 #ifdef CYGPKG_REDBOOT_NETWORKING
197     memcpy(board_info->bi_enetaddr, __local_enet_addr, sizeof(enet_addr_t));
198 #endif
199
200     // adjust SP to 64 bit boundary, and leave a little space
201     // between it and the commandline for PowerPC calling
202     // conventions.
203         
204     sp = (sp-32)&~7;
205
206     if (wait_time_set) {
207         int script_timeout_ms = wait_time * 1000;
208 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
209         unsigned char *hold_script = script;
210         script = (unsigned char *)0;
211 #endif
212         diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
213                     (void *)entry, wait_time);
214         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
215             int res;
216             char line[80];
217             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
218             if (res == _GETS_CTRLC) {
219 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
220                 script = hold_script;  // Re-enable script
221 #endif
222                 return;
223             }
224             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
225         }
226     }
227
228     // Disable interrupts
229     HAL_DISABLE_INTERRUPTS(oldints);
230
231     // Put the caches to sleep.
232     HAL_DCACHE_SYNC();
233     HAL_ICACHE_DISABLE();
234     HAL_DCACHE_DISABLE();
235     HAL_DCACHE_SYNC();
236     HAL_ICACHE_INVALIDATE_ALL();
237     HAL_DCACHE_INVALIDATE_ALL();
238
239 //    diag_printf("entry %08x, sp %08x, info %08x, cmd line %08x, baud %d\n",
240 //              entry, sp, board_info, cline, baud_rate);
241 //    breakpoint();
242     
243     // Call into Linux
244     __asm__ volatile (        
245                        // Start by disabling MMU - the mappings are
246                        // 1-1 so this should not cause any problems
247                        "mfmsr   3\n"
248                        "li      4,0xFFFFFFCF\n"
249                        "and     3,3,4\n"
250                        "sync\n"
251                        "mtmsr   3\n"
252                        "sync\n"
253
254                        // Now set up parameters to jump into linux
255
256                        "mtlr    %0\n"           // set entry address in LR
257                        "mr      1,%1\n"         // set stack pointer
258                        "mr      3,%2\n"         // set board info in R3
259                        "mr      4,%3\n"         // set command line in R4
260                        "blr          \n"        // jump into linux
261                        :
262                        : "r"(entry),"r"(sp),"r"(board_info),"r"(cline)
263                        : "r3", "r4"
264                      
265                      );
266 }
267
268 #endif // CYGSEM_REDBOOT_HAL_LINUX_BOOT
269
270 //=========================================================================
271 // EOF redboot_linux_exec.c