]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - lib_i386/i386_linux.c
* Added support for both PCMCIA slots (at the same time!) on MPC8xx
[karo-tx-uboot.git] / 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 <cmd_boot.h>
27 #include <image.h>
28 #include <zlib.h>
29 #include <asm/byteorder.h>
30 #include <asm/zimage.h>
31
32
33 extern image_header_t header;           /* from cmd_bootm.c */
34
35
36 image_header_t *fake_header(image_header_t *hdr, void *ptr, int size)
37 {
38         /* try each supported image type in order */
39         if (NULL != fake_zimage_header(hdr, ptr, size)) {
40                 return hdr;
41         }
42         
43         return NULL;
44 }
45
46
47 void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
48                 ulong addr, ulong *len_ptr, int   verify)
49 {
50         void *base_ptr;
51         
52         ulong len = 0, checksum;
53         ulong initrd_start, initrd_end;
54         ulong data;
55         image_header_t *hdr = &header;
56         
57         /*
58          * Check if there is an initrd image
59          */
60         if (argc >= 3) {
61                 addr = simple_strtoul(argv[2], NULL, 16);
62                 
63                 printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
64                 
65                 /* Copy header so we can blank CRC field for re-calculation */
66                 memcpy (&header, (char *)addr, sizeof(image_header_t));
67                 
68                 if (ntohl(hdr->ih_magic) != IH_MAGIC) {
69                         printf ("Bad Magic Number\n");
70                         do_reset (cmdtp, flag, argc, argv);
71                 }
72                 
73                 data = (ulong)&header;
74                 len  = sizeof(image_header_t);
75                 
76                 checksum = ntohl(hdr->ih_hcrc);
77                 hdr->ih_hcrc = 0;
78                 
79                 if (crc32 (0, (char *)data, len) != checksum) {
80                         printf ("Bad Header Checksum\n");
81                         do_reset (cmdtp, flag, argc, argv);
82                 }
83                 
84                 print_image_hdr (hdr);
85                 
86                 data = addr + sizeof(image_header_t);
87                 len  = ntohl(hdr->ih_size);
88                 
89                 if (verify) {
90                         ulong csum = 0;
91                         
92                         printf ("   Verifying Checksum ... ");
93                         csum = crc32 (0, (char *)data, len);
94                         if (csum != ntohl(hdr->ih_dcrc)) {
95                                 printf ("Bad Data CRC\n");
96                                 do_reset (cmdtp, flag, argc, argv);
97                         }
98                         printf ("OK\n");
99                 }
100                 
101                 if ((hdr->ih_os   != IH_OS_LINUX)       ||
102                     (hdr->ih_arch != IH_CPU_I386)       ||
103                     (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
104                         printf ("No Linux i386 Ramdisk Image\n");
105                         do_reset (cmdtp, flag, argc, argv);
106                 }
107                 
108                 /*
109                  * Now check if we have a multifile image
110                  */
111         } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
112                 ulong tail    = ntohl(len_ptr[0]) % 4;
113                 int i;
114                 
115                 /* skip kernel length and terminator */
116                 data = (ulong)(&len_ptr[2]);
117                 /* skip any additional image length fields */
118                 for (i=1; len_ptr[i]; ++i)
119                         data += 4;
120                 /* add kernel length, and align */
121                 data += ntohl(len_ptr[0]);
122                 if (tail) {
123                         data += 4 - tail;
124                 }
125                 
126                 len   = ntohl(len_ptr[1]);
127                 
128         } else {
129                 /*
130                  * no initrd image
131                  */
132                 data = 0;
133         }
134         
135 #ifdef  DEBUG
136         if (!data) {
137                 printf ("No initrd\n");
138         }
139 #endif
140         
141         if (data) {
142                 initrd_start = data;
143                 initrd_end   = initrd_start + len;
144                 printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
145                         initrd_start, initrd_end);
146                 memmove ((void *)initrd_start, (void *)data, len);
147                 printf ("OK\n");
148         } else {
149                 initrd_start = 0;
150                 initrd_end = 0;
151         }
152         
153         base_ptr = load_zimage((void*)addr + sizeof(image_header_t), ntohl(hdr->ih_size), 
154                                initrd_start, initrd_end-initrd_start, 0);
155
156         if (NULL == base_ptr) {
157                 printf ("## Kernel loading failed ...\n");
158                 do_reset(cmdtp, flag, argc, argv);
159                 
160         }
161                 
162 #ifdef DEBUG
163         printf ("## Transferring control to Linux (at address %08x) ...\n",
164                 (u32)base_ptr);
165 #endif
166                 
167         /* we assume that the kernel is in place */
168         printf("\nStarting kernel ...\n\n");
169                 
170         boot_zimage(base_ptr);
171         
172 }
173
174