PageRenderTime 36ms CodeModel.GetById 12ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/ppc/boot/simple/misc-embedded.c

https://bitbucket.org/evzijst/gittest
C | 275 lines | 179 code | 29 blank | 67 comment | 32 complexity | 8aaf7497cad6fe4fdfa2731ac5bc911b MD5 | raw file
  1/*
  2 * Originally adapted by Gary Thomas.  Much additional work by
  3 * Cort Dougan <cort@fsmlabs.com>.  On top of that still more work by
  4 * Dan Malek <dmalek@jlc.net>.
  5 *
  6 * Currently maintained by: Tom Rini <trini@kernel.crashing.org>
  7 */
  8
  9#include <linux/config.h>
 10#include <linux/types.h>
 11#include <linux/string.h>
 12#include <asm/bootinfo.h>
 13#include <asm/mmu.h>
 14#include <asm/page.h>
 15#include <asm/residual.h>
 16#if defined(CONFIG_4xx)
 17#include <asm/ibm4xx.h>
 18#elif defined(CONFIG_8xx)
 19#include <asm/mpc8xx.h>
 20#elif defined(CONFIG_8260)
 21#include <asm/mpc8260.h>
 22#endif
 23
 24#include "nonstdio.h"
 25
 26/* The linker tells us where the image is. */
 27extern char __image_begin, __image_end;
 28extern char __ramdisk_begin, __ramdisk_end;
 29extern char _end[];
 30
 31/* Because of the limited amount of memory on embedded, it presents
 32 * loading problems.  The biggest is that we load this boot program
 33 * into a relatively low memory address, and the Linux kernel Bss often
 34 * extends into this space when it get loaded.  When the kernel starts
 35 * and zeros the BSS space, it also writes over the information we
 36 * save here and pass to the kernel (usually board info).
 37 * On these boards, we grab some known memory holes to hold this information.
 38 */
 39char cmd_buf[256];
 40char *cmd_line = cmd_buf;
 41char *avail_ram;
 42char *end_avail;
 43char *zimage_start;
 44
 45/* This is for 4xx treeboot.  It provides a place for the bootrom
 46 * give us a pointer to a rom environment command line.
 47 */
 48char *bootrom_cmdline = "";
 49
 50/* This is the default cmdline that will be given to the user at boot time..
 51 * If none was specified at compile time, we'll give it one that should work.
 52 * -- Tom */
 53#ifdef CONFIG_CMDLINE_BOOL
 54char compiled_string[] = CONFIG_CMDLINE;
 55#endif
 56char ramroot_string[] = "root=/dev/ram";
 57char netroot_string[] = "root=/dev/nfs rw ip=on";
 58
 59/* Serial port to use. */
 60unsigned long com_port;
 61
 62/* We need to make sure that this is before the images to ensure
 63 * that it's in a mapped location. - Tom */
 64bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
 65bd_t *hold_residual = &hold_resid_buf;
 66
 67extern unsigned long serial_init(int chan, bd_t *bp);
 68extern void serial_close(unsigned long com_port);
 69extern unsigned long start;
 70extern void flush_instruction_cache(void);
 71extern void gunzip(void *, int, unsigned char *, int *);
 72extern void embed_config(bd_t **bp);
 73
 74/* Weak function for boards which don't need to build the
 75 * board info struct because they are using PPCBoot/U-Boot.
 76 */
 77void __attribute__ ((weak))
 78embed_config(bd_t **bdp)
 79{
 80}
 81
 82unsigned long
 83load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
 84{
 85	char *cp, ch;
 86	int timer = 0, zimage_size;
 87	unsigned long initrd_size;
 88
 89	/* First, capture the embedded board information.  Then
 90	 * initialize the serial console port.
 91	 */
 92	embed_config(&bp);
 93#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 94	com_port = serial_init(0, bp);
 95#endif
 96
 97	/* Grab some space for the command line and board info.  Since
 98	 * we no longer use the ELF header, but it was loaded, grab
 99	 * that space.
100	 */
101#ifdef CONFIG_MBX
102	/* Because of the way the MBX loads the ELF image, we can't
103	 * tell where we started.  We read a magic variable from the NVRAM
104	 * that gives us the intermediate buffer load address.
105	 */
106	load_addr = *(uint *)0xfa000020;
107	load_addr += 0x10000;		/* Skip ELF header */
108#endif
109	/* copy board data */
110	if (bp)
111		memcpy(hold_residual,bp,sizeof(bd_t));
112
113	/* Set end of memory available to us.  It is always the highest
114	 * memory address provided by the board information.
115	 */
116	end_avail = (char *)(bp->bi_memsize);
117
118	puts("\nloaded at:     "); puthex(load_addr);
119	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
120	if ( (unsigned long)load_addr != (unsigned long)&start ) {
121		puts("relocated to:  "); puthex((unsigned long)&start);
122		puts(" ");
123		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
124		puts("\n");
125	}
126
127	if ( bp ) {
128		puts("board data at: "); puthex((unsigned long)bp);
129		puts(" ");
130		puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
131		puts("\nrelocated to:  ");
132		puthex((unsigned long)hold_residual);
133		puts(" ");
134		puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
135		puts("\n");
136	}
137
138	/*
139	 * We link ourself to an arbitrary low address.  When we run, we
140	 * relocate outself to that address.  __image_being points to
141	 * the part of the image where the zImage is. -- Tom
142	 */
143	zimage_start = (char *)(unsigned long)(&__image_begin);
144	zimage_size = (unsigned long)(&__image_end) -
145			(unsigned long)(&__image_begin);
146
147	initrd_size = (unsigned long)(&__ramdisk_end) -
148		(unsigned long)(&__ramdisk_begin);
149
150	/*
151	 * The zImage and initrd will be between start and _end, so they've
152	 * already been moved once.  We're good to go now. -- Tom
153	 */
154	puts("zimage at:     "); puthex((unsigned long)zimage_start);
155	puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
156	puts("\n");
157
158	if ( initrd_size ) {
159		puts("initrd at:     ");
160		puthex((unsigned long)(&__ramdisk_begin));
161		puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
162	}
163
164	/*
165	 * setup avail_ram - this is the first part of ram usable
166	 * by the uncompress code.  Anything after this program in RAM
167	 * is now fair game. -- Tom
168	 */
169	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
170
171	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
172	puthex((unsigned long)end_avail); puts("\n");
173	puts("\nLinux/PPC load: ");
174	cp = cmd_line;
175	/* This is where we try and pick the right command line for booting.
176	 * If we were given one at compile time, use it.  It Is Right.
177	 * If we weren't, see if we have a ramdisk.  If so, thats root.
178	 * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom
179	 */
180#ifdef CONFIG_CMDLINE_BOOL
181	memcpy (cmd_line, compiled_string, sizeof(compiled_string));
182#else
183	if ( initrd_size )
184		memcpy (cmd_line, ramroot_string, sizeof(ramroot_string));
185	else
186		memcpy (cmd_line, netroot_string, sizeof(netroot_string));
187#endif
188	while ( *cp )
189		putc(*cp++);
190	while (timer++ < 5*1000) {
191		if (tstc()) {
192			while ((ch = getc()) != '\n' && ch != '\r') {
193				if (ch == '\b' || ch == '\177') {
194					if (cp != cmd_line) {
195						cp--;
196						puts("\b \b");
197					}
198				} else if (ch == '\030'		/* ^x */
199					   || ch == '\025') {	/* ^u */
200					while (cp != cmd_line) {
201						cp--;
202						puts("\b \b");
203					}
204				} else {
205					*cp++ = ch;
206					putc(ch);
207				}
208			}
209			break;  /* Exit 'timer' loop */
210		}
211		udelay(1000);  /* 1 msec */
212	}
213	*cp = 0;
214	puts("\nUncompressing Linux...");
215
216	gunzip(0, 0x400000, zimage_start, &zimage_size);
217	flush_instruction_cache();
218	puts("done.\n");
219	{
220		struct bi_record *rec;
221		unsigned long initrd_loc = 0;
222		unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) +
223				(1 << 20) - 1, (1 << 20));
224		rec = (struct bi_record *)rec_loc;
225
226		/* We need to make sure that the initrd and bi_recs do not
227		 * overlap. */
228		if ( initrd_size ) {
229			initrd_loc = (unsigned long)(&__ramdisk_begin);
230			/* If the bi_recs are in the middle of the current
231			 * initrd, move the initrd to the next MB
232			 * boundary. */
233			if ((rec_loc > initrd_loc) &&
234					((initrd_loc + initrd_size)
235					 > rec_loc)) {
236				initrd_loc = _ALIGN((unsigned long)(zimage_size)
237						+ (2 << 20) - 1, (2 << 20));
238			 	memmove((void *)initrd_loc, &__ramdisk_begin,
239					 initrd_size);
240		         	puts("initrd moved:  "); puthex(initrd_loc);
241			 	puts(" "); puthex(initrd_loc + initrd_size);
242			 	puts("\n");
243			}
244		}
245
246		rec->tag = BI_FIRST;
247		rec->size = sizeof(struct bi_record);
248		rec = (struct bi_record *)((unsigned long)rec + rec->size);
249
250		rec->tag = BI_CMD_LINE;
251		memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
252		rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
253		rec = (struct bi_record *)((unsigned long)rec + rec->size);
254
255		if ( initrd_size ) {
256			rec->tag = BI_INITRD;
257			rec->data[0] = initrd_loc;
258			rec->data[1] = initrd_size;
259			rec->size = sizeof(struct bi_record) + 2 *
260				sizeof(unsigned long);
261			rec = (struct bi_record *)((unsigned long)rec +
262					rec->size);
263		}
264
265		rec->tag = BI_LAST;
266		rec->size = sizeof(struct bi_record);
267		rec = (struct bi_record *)((unsigned long)rec + rec->size);
268	}
269	puts("Now booting the kernel\n");
270#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
271	serial_close(com_port);
272#endif
273
274	return (unsigned long)hold_residual;
275}