Merge branch 'develop-3.0' of ssh://10.10.10.29/rk/kernel into develop-3.0
[firefly-linux-kernel-4.4.55.git] / scripts / bmptologo.c
1
2 /*
3  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
4  *  the Linux kernel
5  *
6  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
7  *
8  *  --------------------------------------------------------------------------
9  *
10  *  This file is subject to the terms and conditions of the GNU General Public
11  *  License. See the file COPYING in the main directory of the Linux
12  *  distribution for more details.
13  */
14
15 #include <ctype.h>
16 #include <errno.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <sys/mman.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32
33
34 static const char *programname;
35 static const char *filename;
36 static const char *logoname = "linux_logo";
37 static const char *outputname;
38 static FILE *out;
39
40 //#define debug 0
41 #define LINUX_LOGO_MONO         1       /* monochrome black/white */
42 #define LINUX_LOGO_VGA16        2       /* 16 colors VGA text palette */
43 #define LINUX_LOGO_CLUT224      3       /* 224 colors */
44 #define LINUX_LOGO_GRAY256      4       /* 256 levels grayscale */
45 #define LINUX_LOGO_bmp          5       /* truecolours*/
46
47 static const char *logo_types[LINUX_LOGO_bmp+1] = {
48     [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
49     [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
50     [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
51     [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256",
52     [LINUX_LOGO_bmp] = "LINUX_LOGO_bmp"
53 };
54
55 #define MAX_LINUX_LOGO_COLORS   224
56
57 struct color {
58     char blue;
59     char green;
60     char red;
61 };
62
63 static const struct color clut_vga16[16] = {
64     { 0x00, 0x00, 0x00 },
65     { 0x00, 0x00, 0xaa },
66     { 0x00, 0xaa, 0x00 },
67     { 0x00, 0xaa, 0xaa },
68     { 0xaa, 0x00, 0x00 },
69     { 0xaa, 0x00, 0xaa },
70     { 0xaa, 0x55, 0x00 },
71     { 0xaa, 0xaa, 0xaa },
72     { 0x55, 0x55, 0x55 },
73     { 0x55, 0x55, 0xff },
74     { 0x55, 0xff, 0x55 },
75     { 0x55, 0xff, 0xff },
76     { 0xff, 0x55, 0x55 },
77     { 0xff, 0x55, 0xff },
78     { 0xff, 0xff, 0x55 },
79     { 0xff, 0xff, 0xff },
80 };
81
82 unsigned char data_name[] = {
83         0x6C, 0x6F, 0x67,
84         0x6F, 0x5F, 0x52,
85         0x4B, 0x6C, 0x6F,
86         0x67, 0x6F, 0x5F,
87         0x64, 0x61, 0x74,
88         0x61
89 };
90
91 unsigned char clut_name[] = {
92         0x62, 0x6D, 0x70,
93         0x6C, 0x6F, 0x67,
94         0x6F, 0x5F, 0x52,
95         0x4B, 0x6C, 0x6F,
96         0x67, 0x6F, 0x5F,
97         0x63, 0x6C, 0x75,
98         0x74, 0x00
99 };
100
101 static int logo_type = LINUX_LOGO_CLUT224;
102 static unsigned long logo_width;
103 static unsigned long logo_height;
104 static unsigned long data_long;
105 static unsigned long data_start;
106 static unsigned char *logo_data;
107 static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
108 static unsigned int logo_clutsize;
109
110 static void die(const char *fmt, ...)
111     __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
112 static void usage(void) __attribute ((noreturn));
113
114 static unsigned int get_number(FILE *fp)
115 {
116     int c, val;
117
118     /* Skip leading whitespace */
119     do {
120         c = fgetc(fp);
121         if (c == EOF)
122             die("%s: end of file\n", filename);
123         if (c == '#') {
124             /* Ignore comments 'till end of line */
125             do {
126                 c = fgetc(fp);
127                 if (c == EOF)
128                     die("%s: end of file\n", filename);
129             } while (c != '\n');
130         }
131     } while (isspace(c));
132
133     /* Parse decimal number */
134     val = 0;
135     while (isdigit(c)) {
136         val = 10*val+c-'0';
137         c = fgetc(fp);
138         if (c == EOF)
139             die("%s: end of file\n", filename);
140     }
141     return val;
142 }
143
144 static unsigned int get_number255(FILE *fp, unsigned int maxval)
145 {
146     unsigned int val = get_number(fp);
147     return (255*val+maxval/2)/maxval;
148 }
149
150 static void read_image(void)
151 {
152         FILE *fp;
153         unsigned long i;
154         struct stat s;
155         char j = 0;
156         int magic;
157         unsigned int maxval;
158         char read_buf[0x28];
159         long ret = 0;
160         unsigned char *data;
161         
162         /* open image file */
163         fp = open(filename, O_RDONLY);
164         if (!fp)
165                 die("Cannot open file isll.. %s: %s\n", filename, strerror(errno));
166
167         if (fstat(fp, &s) < 0) {
168         die("Cannot stat file isll.. %s: %s\n", filename, strerror(errno));
169     }
170 #if 0
171         ret = fread(read_buf,1,0x26,fp);
172         if (ret != 0x26)
173                 die("read file %s: error read_buf=%ld\n", filename,ret);
174
175         logo_height = (read_buf[0x19]<<24) + (read_buf[0x18]<<16) +(read_buf[0x17]<<8) +(read_buf[0x16]);
176         logo_width  = (read_buf[0x15]<<24) + (read_buf[0x14]<<16) +(read_buf[0x13]<<8) +(read_buf[0x12]);
177         data_start = (read_buf[0x0d]<<24) + (read_buf[0x0c]<<16) +(read_buf[0x0b]<<8) +(read_buf[0x0a]);
178         data_long  = (read_buf[0x25]<<24) + (read_buf[0x24]<<16) +(read_buf[0x023]<<8) +(read_buf[0x22]);
179 #endif  
180         /* allocate image data */
181         //logo_data = (char *)malloc(logo_height * logo_width * 3);
182         //data_long = logo_height * logo_width * 3;
183 //#ifdef debug
184 #if 0
185         die("%s..logo_height=%ld,logo_width=%ld,data_start=%ld,data_long=%ld,sizeof(struct color)=%d,  \
186                 read_buf[0x17]=%d  read_buf[0x13]=%d\n\n",filename,logo_height,logo_width,data_start,  \
187                 data_long,sizeof(struct color),read_buf[0x17],read_buf[0x13]);
188         if ((logo_width*logo_height*3) != data_long)
189                 die("something is wront in scripts/bmptologo.c\n");
190
191 #endif
192 #if 0
193         fseek(fp,data_start,SEEK_SET);
194         ret = fread(logo_data,1,data_long,fp);
195         if (ret != data_long)
196                 die("read file %s: error logo_data=%ld\n", filename,ret);
197 #else
198     data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fp, 0);
199     if (data == MAP_FAILED)
200         die("read file %s: error logo_data\n", filename);
201         logo_data = data + 54;
202         logo_height = (data[0x19]<<24) + (data[0x18]<<16) +(data[0x17]<<8) +(data[0x16]);
203         logo_width  = (data[0x15]<<24) + (data[0x14]<<16) +(data[0x13]<<8) +(data[0x12]);
204         data_start = (data[0x0d]<<24) + (data[0x0c]<<16) +(data[0x0b]<<8) +(data[0x0a]);
205         data_long  = (data[0x25]<<24) + (data[0x24]<<16) +(data[0x023]<<8) +(data[0x22]);
206         data_long = logo_height * logo_width * 3;
207 #if 0
208         die("%s..logo_height=%ld,logo_width=%ld,data_start=%ld,data_long=%ld,sizeof(struct color)=%d,  \
209                 read_buf[0x17]=%d  read_buf[0x13]=%d\n\n",filename,logo_height,logo_width,data_start,  \
210                 data_long,sizeof(struct color),read_buf[0x17],read_buf[0x13]);
211         if ((logo_width*logo_height*3) != data_long)
212                 die("something is wront in scripts/bmptologo.c\n");
213 #endif  
214 #endif
215 #ifdef  debug
216         die("logo_data is:%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x:over\n", \
217                 logo_data[0],logo_data[1],logo_data[2],logo_data[3],logo_data[4],logo_data[5],logo_data[6],logo_data[7],logo_data[8], \
218 logo_data[9],logo_data[10],logo_data[11]);
219 #endif
220     /* close file */
221     close(fp);
222 }
223
224
225 static inline int is_black(struct color c)
226 {
227     return c.red == 0 && c.green == 0 && c.blue == 0;
228 }
229
230 static inline int is_white(struct color c)
231 {
232     return c.red == 255 && c.green == 255 && c.blue == 255;
233 }
234
235 static inline int is_gray(struct color c)
236 {
237     return c.red == c.green && c.red == c.blue;
238 }
239
240 static inline int is_equal(struct color c1, struct color c2)
241 {
242     return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
243 }
244
245 static int write_hex_cnt;
246
247 static void write_hex(unsigned char byte)
248 {
249     if (write_hex_cnt % 12)
250         fprintf(out, ", 0x%02x", byte);
251     else if (write_hex_cnt)
252         fprintf(out, ",\n\t0x%02x", byte);
253     else
254         fprintf(out, "\t0x%02x", byte);
255     write_hex_cnt++;
256 }
257
258 static void write_header(void)
259 {
260         /* open logo file */
261         if (outputname) {
262                 out = fopen(outputname, "w");
263                 if (!out)
264                         die("Cannot create file %s: %s\n", outputname, strerror(errno));
265         } else {
266                 out = stdout;
267         }
268
269         fputs("/*\n", out);
270         fputs(" *  DO NOT EDIT THIS FILE!\n", out);
271         fputs(" *\n", out);
272         fprintf(out, " *  It was automatically generated from %s\n", filename);
273         fputs(" *\n", out);
274         fprintf(out, " *  Linux logo %s\n", logoname);
275         fputs(" */\n\n", out);
276         fputs("#include <linux/linux_logo.h>\n\n", out);
277         fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
278                 logoname);
279 }
280
281 static void write_footer(void)
282 {
283         fputs("\n};\n\n", out);
284         fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
285         fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
286
287         if (logo_type == LINUX_LOGO_bmp) {
288                 fprintf(out, "\t.width\t\t= %ld,\n",  logo_width);
289                 fprintf(out, "\t.height\t\t= %ld,\n",  logo_height);
290                 //fprintf(out, "\t.data\t\t= %s_data,\n", logoname);
291                 fprintf(out, "\t.data\t\t= &(%s_data[%ld]),\n", logoname,sizeof(data_name) + 8);
292                 fprintf(out, "\t.clut\t\t= %s_clut\n", logoname);
293         }  
294
295         fputs("};\n\n", out);
296
297         /* close logo file */
298         if (outputname)
299                 fclose(out);
300 }
301
302
303 static void write_logo_bmp(void)
304 {
305         unsigned long  i=0, j=0;
306         unsigned char *position ;
307         
308         /* validate image */
309 /*statistics how many colours ,and if have over 224
310         logo_clutsize = 0;
311         for (i = 0; i < logo_height; i++)
312                 for (j = 0; j < logo_width; j++) {
313                         for (k = 0; k < logo_clutsize; k++)
314                                 if (is_equal(logo_data[i][j], logo_clut[k]))
315                                         break;
316                         if (k == logo_clutsize) {
317                                 if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
318                                         die("Image has more than %d colors\n"
319                                                 "Use ppmquant(1) to reduce the number of colors\n",
320                                                 MAX_LINUX_LOGO_COLORS);
321                                         logo_clut[logo_clutsize++] = logo_data[i][j];
322                         }
323                 }
324
325 */
326         write_hex_cnt = 0;
327
328         
329         /* write file header */
330         write_header();
331 #if 1
332         write_hex((unsigned char)(logo_width >> 8));
333         write_hex((unsigned char)logo_width);
334         write_hex((unsigned char)(logo_height >> 8));
335         write_hex((unsigned char)logo_height);
336
337         for (i = 0; i < sizeof(data_name); i++){
338                 write_hex(data_name[i]);
339         }
340         write_hex((unsigned char)(logo_width >> 8));
341         write_hex((unsigned char)logo_width);
342         write_hex((unsigned char)(logo_height >> 8));
343         write_hex((unsigned char)logo_height);
344 #endif
345         
346 #if 0
347         /* write logo data */
348         for (i = 0; i < logo_height; i++)
349                 for (j = 0; j < logo_width; j++) {
350                         for (k = 0; k < logo_clutsize; k++)
351                                 if (is_equal(logo_data[i][j], logo_clut[k]))
352                                         break;
353                         write_hex(k+32);
354                 }
355         fputs("\n};\n\n", out);
356
357         
358
359         /* write logo clut */
360         fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
361                 logoname);
362
363         write_hex_cnt = 0;
364
365         for (i = 0; i < sizeof(clut_name); i++){
366                 write_hex(clut_name[i]);
367         }
368         write_hex(logo_clutsize);
369
370         for (i = 0; i < logo_clutsize; i++) {
371                 write_hex(logo_clut[i].red);
372                 write_hex(logo_clut[i].green);
373                 write_hex(logo_clut[i].blue);
374         }
375
376         for (i = logo_clutsize; i < (MAX_LINUX_LOGO_COLORS * 3); i++)
377         {
378                 write_hex(32);
379         }
380
381         /* write logo structure and file footer */
382 #endif
383
384 #if 1
385         for (i=logo_height; i>0; i--)
386         {
387                 for (j=0; j<logo_width; j++)
388                 {       
389                                 position = logo_data + (i-1)* logo_width * 3 + 3 * j;
390 #if 0
391                         write_hex(*(position));
392                         write_hex(*(position+1));
393                         write_hex(*(position+2));
394 #else
395                         write_hex(*(position));
396                         write_hex(*(position+1));
397                         write_hex(*(position+2));               
398                         write_hex(0);
399 #endif
400                 }
401         }
402 #endif
403
404         fputs("\n};\n\n", out);
405         /* write logo clut */
406         fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
407                 logoname);
408
409         write_hex_cnt = 0;
410         for (i = 0; i < sizeof(clut_name); i++){
411                 write_hex(clut_name[i]);
412         }
413         
414         write_footer();
415 }
416
417 static void die(const char *fmt, ...)
418 {
419     va_list ap;
420
421     va_start(ap, fmt);
422     vfprintf(stderr, fmt, ap);
423     va_end(ap);
424
425     exit(1);
426 }
427
428 static void usage(void)
429 {
430     die("\n"
431         "Usage: %s [options] <filename>\n"
432         "\n"
433         "Valid options:\n"
434         "    -h          : display this usage information\n"
435         "    -n <name>   : specify logo name (default: linux_logo)\n"
436         "    -o <output> : output to file <output> instead of stdout\n"
437         "    -t <type>   : specify logo type, one of\n"                       
438         "                      bmp : truecolour\n"
439         "\n", programname);
440 }
441
442 int main(int argc, char *argv[])
443 {
444     int opt;
445
446     programname = argv[0];
447
448     opterr = 0;
449     while (1) {
450         opt = getopt(argc, argv, "hn:o:t:");
451         if (opt == -1)
452             break;
453
454         switch (opt) {
455             case 'h':
456                 usage();
457                 break;
458
459             case 'n':
460                 logoname = optarg;
461                 break;
462
463             case 'o':
464                 outputname = optarg;
465                 break;
466
467             case 't':
468                 if (!strcmp(optarg, "bmp"))
469                     logo_type = LINUX_LOGO_bmp;         
470                 else
471                         die("logo_type is wrong without bmp\n");
472                 break;
473
474             default:
475                 usage();
476                 break;
477         }
478     }
479     if (optind != argc-1)
480         usage();
481
482     filename = argv[optind];
483
484         read_image();
485     switch (logo_type) {
486         case LINUX_LOGO_bmp:
487                 write_logo_bmp();
488             break;
489         default :
490                 die("logo_type is wrong\n");
491     }
492     exit(0);
493 }
494