]>
Commit | Line | Data |
---|---|---|
2262cfee WD |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
4 | * Marius Groeger <[email protected]> | |
5 | * | |
6 | * Copyright (C) 2001 Erik Mouw ([email protected]) | |
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> | |
2262cfee WD |
26 | #include <image.h> |
27 | #include <zlib.h> | |
28 | #include <asm/byteorder.h> | |
29 | #include <asm/zimage.h> | |
30 | ||
8bde7f77 WD |
31 | /*cmd_boot.c*/ |
32 | extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
2262cfee WD |
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 | } | |
8bde7f77 | 43 | |
2262cfee WD |
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 | { | |
ea909b76 | 51 | void *base_ptr; |
8bde7f77 | 52 | |
2262cfee WD |
53 | ulong len = 0, checksum; |
54 | ulong initrd_start, initrd_end; | |
55 | ulong data; | |
56 | image_header_t *hdr = &header; | |
8bde7f77 | 57 | |
2262cfee WD |
58 | /* |
59 | * Check if there is an initrd image | |
60 | */ | |
61 | if (argc >= 3) { | |
62 | addr = simple_strtoul(argv[2], NULL, 16); | |
8bde7f77 | 63 | |
2262cfee | 64 | printf ("## Loading Ramdisk Image at %08lx ...\n", addr); |
8bde7f77 | 65 | |
2262cfee WD |
66 | /* Copy header so we can blank CRC field for re-calculation */ |
67 | memcpy (&header, (char *)addr, sizeof(image_header_t)); | |
8bde7f77 | 68 | |
2262cfee WD |
69 | if (ntohl(hdr->ih_magic) != IH_MAGIC) { |
70 | printf ("Bad Magic Number\n"); | |
71 | do_reset (cmdtp, flag, argc, argv); | |
72 | } | |
8bde7f77 | 73 | |
2262cfee WD |
74 | data = (ulong)&header; |
75 | len = sizeof(image_header_t); | |
8bde7f77 | 76 | |
2262cfee WD |
77 | checksum = ntohl(hdr->ih_hcrc); |
78 | hdr->ih_hcrc = 0; | |
8bde7f77 | 79 | |
2262cfee WD |
80 | if (crc32 (0, (char *)data, len) != checksum) { |
81 | printf ("Bad Header Checksum\n"); | |
82 | do_reset (cmdtp, flag, argc, argv); | |
83 | } | |
8bde7f77 | 84 | |
2262cfee | 85 | print_image_hdr (hdr); |
8bde7f77 | 86 | |
2262cfee WD |
87 | data = addr + sizeof(image_header_t); |
88 | len = ntohl(hdr->ih_size); | |
8bde7f77 | 89 | |
2262cfee WD |
90 | if (verify) { |
91 | ulong csum = 0; | |
8bde7f77 | 92 | |
2262cfee WD |
93 | printf (" Verifying Checksum ... "); |
94 | csum = crc32 (0, (char *)data, len); | |
95 | if (csum != ntohl(hdr->ih_dcrc)) { | |
96 | printf ("Bad Data CRC\n"); | |
97 | do_reset (cmdtp, flag, argc, argv); | |
98 | } | |
99 | printf ("OK\n"); | |
100 | } | |
8bde7f77 | 101 | |
2262cfee WD |
102 | if ((hdr->ih_os != IH_OS_LINUX) || |
103 | (hdr->ih_arch != IH_CPU_I386) || | |
104 | (hdr->ih_type != IH_TYPE_RAMDISK) ) { | |
105 | printf ("No Linux i386 Ramdisk Image\n"); | |
106 | do_reset (cmdtp, flag, argc, argv); | |
107 | } | |
8bde7f77 | 108 | |
2262cfee WD |
109 | /* |
110 | * Now check if we have a multifile image | |
111 | */ | |
112 | } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { | |
113 | ulong tail = ntohl(len_ptr[0]) % 4; | |
114 | int i; | |
8bde7f77 | 115 | |
2262cfee WD |
116 | /* skip kernel length and terminator */ |
117 | data = (ulong)(&len_ptr[2]); | |
118 | /* skip any additional image length fields */ | |
119 | for (i=1; len_ptr[i]; ++i) | |
120 | data += 4; | |
121 | /* add kernel length, and align */ | |
122 | data += ntohl(len_ptr[0]); | |
123 | if (tail) { | |
124 | data += 4 - tail; | |
125 | } | |
8bde7f77 | 126 | |
2262cfee | 127 | len = ntohl(len_ptr[1]); |
8bde7f77 | 128 | |
2262cfee WD |
129 | } else { |
130 | /* | |
131 | * no initrd image | |
132 | */ | |
133 | data = 0; | |
134 | } | |
8bde7f77 | 135 | |
2262cfee WD |
136 | #ifdef DEBUG |
137 | if (!data) { | |
138 | printf ("No initrd\n"); | |
139 | } | |
140 | #endif | |
8bde7f77 | 141 | |
2262cfee WD |
142 | if (data) { |
143 | initrd_start = data; | |
144 | initrd_end = initrd_start + len; | |
145 | printf (" Loading Ramdisk to %08lx, end %08lx ... ", | |
146 | initrd_start, initrd_end); | |
147 | memmove ((void *)initrd_start, (void *)data, len); | |
148 | printf ("OK\n"); | |
149 | } else { | |
150 | initrd_start = 0; | |
151 | initrd_end = 0; | |
152 | } | |
8bde7f77 WD |
153 | |
154 | base_ptr = load_zimage((void*)addr + sizeof(image_header_t), ntohl(hdr->ih_size), | |
2262cfee WD |
155 | initrd_start, initrd_end-initrd_start, 0); |
156 | ||
157 | if (NULL == base_ptr) { | |
158 | printf ("## Kernel loading failed ...\n"); | |
159 | do_reset(cmdtp, flag, argc, argv); | |
8bde7f77 | 160 | |
2262cfee | 161 | } |
8bde7f77 | 162 | |
2262cfee WD |
163 | #ifdef DEBUG |
164 | printf ("## Transferring control to Linux (at address %08x) ...\n", | |
165 | (u32)base_ptr); | |
166 | #endif | |
8bde7f77 | 167 | |
2262cfee WD |
168 | /* we assume that the kernel is in place */ |
169 | printf("\nStarting kernel ...\n\n"); | |
2262cfee | 170 | |
8bde7f77 | 171 | boot_zimage(base_ptr); |
2262cfee | 172 | |
8bde7f77 | 173 | } |