]> git.ipfire.org Git - people/ms/u-boot.git/blob - tools/imls/imls.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / tools / imls / imls.c
1 /*
2 * (C) Copyright 2009 Marco Stornelli
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stddef.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/ioctl.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17 #include <asm/page.h>
18
19 #ifdef MTD_OLD
20 #include <stdint.h>
21 #include <linux/mtd/mtd.h>
22 #else
23 #define __user /* nothing */
24 #include <mtd/mtd-user.h>
25 #endif
26
27 #include <sha1.h>
28 #include <libfdt.h>
29 #include <fdt_support.h>
30 #include <image.h>
31
32 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
33
34 extern unsigned long crc32(unsigned long crc, const char *buf, unsigned int len);
35 static void usage(void);
36 static int image_verify_header(char *ptr, int fd);
37 static int flash_bad_block(int fd, uint8_t mtd_type, loff_t start);
38
39 char *cmdname;
40 char *devicefile;
41
42 unsigned int sectorcount = 0;
43 int sflag = 0;
44 unsigned int sectoroffset = 0;
45 unsigned int sectorsize = 0;
46 int cflag = 0;
47
48 int main (int argc, char **argv)
49 {
50 int fd = -1, err = 0, readbyte = 0, j;
51 struct mtd_info_user mtdinfo;
52 char buf[sizeof(image_header_t)];
53 int found = 0;
54
55 cmdname = *argv;
56
57 while (--argc > 0 && **++argv == '-') {
58 while (*++*argv) {
59 switch (**argv) {
60 case 'c':
61 if (--argc <= 0)
62 usage ();
63 sectorcount = (unsigned int)atoi(*++argv);
64 cflag = 1;
65 goto NXTARG;
66 case 'o':
67 if (--argc <= 0)
68 usage ();
69 sectoroffset = (unsigned int)atoi(*++argv);
70 goto NXTARG;
71
72 case 's':
73 if (--argc <= 0)
74 usage ();
75 sectorsize = (unsigned int)atoi(*++argv);
76 sflag = 1;
77 goto NXTARG;
78 default:
79 usage ();
80 }
81 }
82 NXTARG: ;
83 }
84
85 if (argc != 1 || cflag == 0 || sflag == 0)
86 usage();
87
88 devicefile = *argv;
89
90 fd = open(devicefile, O_RDONLY);
91 if (fd < 0) {
92 fprintf (stderr, "%s: Can't open %s: %s\n",
93 cmdname, devicefile, strerror(errno));
94 exit(EXIT_FAILURE);
95 }
96
97 err = ioctl(fd, MEMGETINFO, &mtdinfo);
98 if (err < 0) {
99 fprintf(stderr, "%s: Cannot get MTD information: %s\n",cmdname,
100 strerror(errno));
101 exit(EXIT_FAILURE);
102 }
103
104 if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) {
105 fprintf(stderr, "%s: Unsupported flash type %u\n",
106 cmdname, mtdinfo.type);
107 exit(EXIT_FAILURE);
108 }
109
110 if (sectorsize * sectorcount != mtdinfo.size) {
111 fprintf(stderr, "%s: Partition size (%d) incompatible with "
112 "sector size and count\n", cmdname, mtdinfo.size);
113 exit(EXIT_FAILURE);
114 }
115
116 if (sectorsize * sectoroffset >= mtdinfo.size) {
117 fprintf(stderr, "%s: Partition size (%d) incompatible with "
118 "sector offset given\n", cmdname, mtdinfo.size);
119 exit(EXIT_FAILURE);
120 }
121
122 if (sectoroffset > sectorcount - 1) {
123 fprintf(stderr, "%s: Sector offset cannot be grater than "
124 "sector count minus one\n", cmdname);
125 exit(EXIT_FAILURE);
126 }
127
128 printf("Searching....\n");
129
130 for (j = sectoroffset; j < sectorcount; ++j) {
131
132 if (lseek(fd, j*sectorsize, SEEK_SET) != j*sectorsize) {
133 fprintf(stderr, "%s: lseek failure: %s\n",
134 cmdname, strerror(errno));
135 exit(EXIT_FAILURE);
136 }
137
138 err = flash_bad_block(fd, mtdinfo.type, j*sectorsize);
139 if (err < 0)
140 exit(EXIT_FAILURE);
141 if (err)
142 continue; /* Skip and jump to next */
143
144 readbyte = read(fd, buf, sizeof(image_header_t));
145 if (readbyte != sizeof(image_header_t)) {
146 fprintf(stderr, "%s: Can't read from device: %s\n",
147 cmdname, strerror(errno));
148 exit(EXIT_FAILURE);
149 }
150
151 if (fdt_check_header(buf)) {
152 /* old-style image */
153 if (image_verify_header(buf, fd)) {
154 found = 1;
155 image_print_contents((image_header_t *)buf);
156 }
157 } else {
158 /* FIT image */
159 fit_print_contents(buf);
160 }
161
162 }
163
164 close(fd);
165
166 if(!found)
167 printf("No images found\n");
168
169 exit(EXIT_SUCCESS);
170 }
171
172 void usage()
173 {
174 fprintf (stderr, "Usage:\n"
175 " %s [-o offset] -s size -c count device\n"
176 " -o ==> number of sectors to use as offset\n"
177 " -c ==> number of sectors\n"
178 " -s ==> size of sectors (byte)\n",
179 cmdname);
180
181 exit(EXIT_FAILURE);
182 }
183
184 static int image_verify_header(char *ptr, int fd)
185 {
186 int len, nread;
187 char *data;
188 uint32_t checksum;
189 image_header_t *hdr = (image_header_t *)ptr;
190 char buf[PAGE_SIZE];
191
192 if (image_get_magic(hdr) != IH_MAGIC)
193 return 0;
194
195 data = (char *)hdr;
196 len = image_get_header_size();
197
198 checksum = image_get_hcrc(hdr);
199 hdr->ih_hcrc = htonl(0); /* clear for re-calculation */
200
201 if (crc32(0, data, len) != checksum) {
202 fprintf(stderr,
203 "%s: Maybe image found but it has bad header checksum!\n",
204 cmdname);
205 return 0;
206 }
207
208 len = image_get_size(hdr);
209 checksum = 0;
210
211 while (len > 0) {
212 nread = read(fd, buf, MIN(len,PAGE_SIZE));
213 if (nread != MIN(len,PAGE_SIZE)) {
214 fprintf(stderr,
215 "%s: Error while reading: %s\n",
216 cmdname, strerror(errno));
217 exit(EXIT_FAILURE);
218 }
219 checksum = crc32(checksum, buf, nread);
220 len -= nread;
221 }
222
223 if (checksum != image_get_dcrc(hdr)) {
224 fprintf (stderr,
225 "%s: Maybe image found but it has corrupted data!\n",
226 cmdname);
227 return 0;
228 }
229
230 return 1;
231 }
232
233 /*
234 * Test for bad block on NAND, just returns 0 on NOR, on NAND:
235 * 0 - block is good
236 * > 0 - block is bad
237 * < 0 - failed to test
238 */
239 static int flash_bad_block(int fd, uint8_t mtd_type, loff_t start)
240 {
241 if (mtd_type == MTD_NANDFLASH) {
242 int badblock = ioctl(fd, MEMGETBADBLOCK, &start);
243
244 if (badblock < 0) {
245 fprintf(stderr,"%s: Cannot read bad block mark: %s\n",
246 cmdname, strerror(errno));
247 return badblock;
248 }
249
250 if (badblock) {
251 return badblock;
252 }
253 }
254
255 return 0;
256 }