]> git.sur5r.net Git - u-boot/blob - lib_i386/i386_linux.c
67a78c4e3bfcf3803bea8bdcd675b71aa533ecb2
[u-boot] / lib_i386 / i386_linux.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <image.h>
27 #include <zlib.h>
28 #include <asm/byteorder.h>
29 #include <asm/zimage.h>
30
31 /*cmd_boot.c*/
32 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
33
34 extern image_header_t header;           /* from cmd_bootm.c */
35
36
37 image_header_t *fake_header(image_header_t *hdr, void *ptr, int size)
38 {
39         /* try each supported image type in order */
40         if (NULL != fake_zimage_header(hdr, ptr, size)) {
41                 return hdr;
42         }
43
44         return NULL;
45 }
46
47
48 void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
49                 ulong addr, ulong *len_ptr, int   verify)
50 {
51         void *base_ptr;
52
53         ulong len = 0;
54         ulong initrd_start, initrd_end;
55         ulong data;
56         image_header_t *hdr = &header;
57
58         /*
59          * Check if there is an initrd image
60          */
61         if (argc >= 3) {
62                 addr = simple_strtoul(argv[2], NULL, 16);
63                 hdr = (image_header_t *)addr;
64
65                 printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
66
67                 if (!image_check_magic (hdr)) {
68                         printf ("Bad Magic Number\n");
69                         do_reset (cmdtp, flag, argc, argv);
70                 }
71
72                 if (!image_check_hcrc (hdr)) {
73                         printf ("Bad Header Checksum\n");
74                         do_reset (cmdtp, flag, argc, argv);
75                 }
76
77                 print_image_hdr (hdr);
78
79                 data = image_get_data (hdr);
80                 len = image_get_data_size (hdr);
81
82                 if (verify) {
83                         printf ("   Verifying Checksum ... ");
84                         if (!image_check_dcrc (hdr)) {
85                                 printf ("Bad Data CRC\n");
86                                 do_reset (cmdtp, flag, argc, argv);
87                         }
88                         printf ("OK\n");
89                 }
90
91                 if (!image_check_os (hdr, IH_OS_LINUX) ||
92                     !image_check_arch (hdr, IH_ARCH_I386) ||
93                     !image_check_type (hdr, IH_TYPE_RAMDISK)) {
94                         printf ("No Linux i386 Ramdisk Image\n");
95                         do_reset (cmdtp, flag, argc, argv);
96                 }
97
98                 /*
99                  * Now check if we have a multifile image
100                  */
101         } else if (image_check_type (hdr, IH_TYPE_MULTI) && (len_ptr[1])) {
102                 ulong tail    = image_to_cpu (len_ptr[0]) % 4;
103                 int i;
104
105                 /* skip kernel length and terminator */
106                 data = (ulong)(&len_ptr[2]);
107                 /* skip any additional image length fields */
108                 for (i=1; len_ptr[i]; ++i)
109                         data += 4;
110                 /* add kernel length, and align */
111                 data += image_to_cpu (len_ptr[0]);
112                 if (tail) {
113                         data += 4 - tail;
114                 }
115
116                 len   = image_to_cpu (len_ptr[1]);
117
118         } else {
119                 /*
120                  * no initrd image
121                  */
122                 data = 0;
123         }
124
125 #ifdef  DEBUG
126         if (!data) {
127                 printf ("No initrd\n");
128         }
129 #endif
130
131         if (data) {
132                 initrd_start = data;
133                 initrd_end   = initrd_start + len;
134                 printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
135                         initrd_start, initrd_end);
136                 memmove ((void *)initrd_start, (void *)data, len);
137                 printf ("OK\n");
138         } else {
139                 initrd_start = 0;
140                 initrd_end = 0;
141         }
142
143         /* if multi-part image, we need to advance base ptr */
144         if (image_check_type (hdr, IH_TYPE_MULTI) && (len_ptr[1])) {
145                 int i;
146                 for (i=0, addr+=sizeof(int); len_ptr[i++]; addr+=sizeof(int));
147         }
148
149         base_ptr = load_zimage((void*)addr + image_get_header_size (),
150                                image_get_data_size (hdr),
151                                initrd_start, initrd_end-initrd_start, 0);
152
153         if (NULL == base_ptr) {
154                 printf ("## Kernel loading failed ...\n");
155                 do_reset(cmdtp, flag, argc, argv);
156
157         }
158
159 #ifdef DEBUG
160         printf ("## Transferring control to Linux (at address %08x) ...\n",
161                 (u32)base_ptr);
162 #endif
163
164         /* we assume that the kernel is in place */
165         printf("\nStarting kernel ...\n\n");
166
167         boot_zimage(base_ptr);
168
169 }