2 * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * This utility sorts sysinit structure entries in binary format and
28 * prints out the result in C-format.
42 static const char *input_f
;
43 static const char *output_f
;
44 static const char *struct_name
;
45 static const char *keyword
;
46 static struct sysinit_data
**start
;
47 static struct sysinit_data
**stop
;
49 static int input_file
= -1;
50 static int output_file
= -1;
52 static uint8_t *input_ptr
;
53 static uint32_t input_len
;
55 static uint32_t endian32
;
57 static char scratch_buf
[4096];
61 static void do_sysinit(void);
63 /* the following function converts the numbers into host endian format */
75 temp
|= (val
& 0xF) << ((endian
& 0xF) * 4);
83 do_write(int fd
, const char *buf
)
85 int len
= strlen(buf
);
87 if (write(fd
, buf
, len
) != len
)
88 err(EX_SOFTWARE
, "Could not write to output file");
98 errx(EX_SOFTWARE
, "Could not allocate memory");
105 errx(EX_USAGE
, "sysinit -i sysinit.bin -o sysinit_data.c \\\n"
106 "\t" "-k sysinit -s sysinit_data [ -R (reverse)]");
112 if (output_file
>= 0)
123 compare(const void *_pa
, const void *_pb
)
125 const struct sysinit_data
* const *pa
= _pa
;
126 const struct sysinit_data
* const *pb
= _pb
;
128 if ((*pa
)->dw_msb_value
> (*pb
)->dw_msb_value
)
131 if ((*pa
)->dw_msb_value
< (*pb
)->dw_msb_value
)
134 if ((*pa
)->dw_lsb_value
> (*pb
)->dw_lsb_value
)
137 if ((*pa
)->dw_lsb_value
< (*pb
)->dw_lsb_value
)
140 return (0); /* equal */
144 compare_R(const void *_pa
, const void *_pb
)
146 const struct sysinit_data
* const *pa
= _pa
;
147 const struct sysinit_data
* const *pb
= _pb
;
149 if ((*pa
)->dw_msb_value
> (*pb
)->dw_msb_value
)
152 if ((*pa
)->dw_msb_value
< (*pb
)->dw_msb_value
)
155 if ((*pa
)->dw_lsb_value
> (*pb
)->dw_lsb_value
)
158 if ((*pa
)->dw_lsb_value
< (*pb
)->dw_lsb_value
)
161 return (0); /* equal */
165 main(int argc
, char **argv
)
167 struct sysinit_data
**sipp
;
172 while ((c
= getopt(argc
, argv
, "k:s:i:o:Rh")) != -1) {
187 struct_name
= optarg
;
194 if (input_f
== NULL
|| output_f
== NULL
||
195 struct_name
== NULL
|| keyword
== NULL
)
202 input_file
= open(input_f
, O_RDONLY
);
204 err(EX_SOFTWARE
, "Could not open input file: %s", input_f
);
206 output_file
= open(output_f
, O_TRUNC
| O_CREAT
| O_RDWR
, 0600);
208 err(EX_SOFTWARE
, "Could not open output file: %s", output_f
);
210 off
= lseek(input_file
, 0, SEEK_END
);
212 input_ptr
= do_malloc(off
);
215 if (input_len
% (uint32_t)sizeof(struct sysinit_data
)) {
216 errx(EX_SOFTWARE
, "Input file size is not divisible by %u",
217 (unsigned int)sizeof(struct sysinit_data
));
219 off
= lseek(input_file
, 0, SEEK_SET
);
221 err(EX_SOFTWARE
, "Could not seek to start of input file");
223 if (read(input_file
, input_ptr
, input_len
) != input_len
)
224 err(EX_SOFTWARE
, "Could not read input file");
226 entries
= input_len
/ (uint32_t)sizeof(struct sysinit_data
);
228 start
= do_malloc(sizeof(void *) * entries
);
229 stop
= start
+ entries
;
231 for (c
= 0; c
!= entries
; c
++)
232 start
[c
] = &((struct sysinit_data
*)input_ptr
)[c
];
235 endian32
= (*start
)->dw_endian32
;
237 /* switch all fields to host endian order */
238 for (sipp
= start
; sipp
< stop
; sipp
++) {
239 (*sipp
)->dw_lsb_value
= read32((*sipp
)->dw_lsb_value
);
240 (*sipp
)->dw_msb_value
= read32((*sipp
)->dw_msb_value
);
241 (*sipp
)->dw_file_line
= read32((*sipp
)->dw_file_line
);
245 /* sort entries, rising numerical order */
246 qsort(start
, entries
, sizeof(void *), &compare
);
248 /* sort entries, falling numerical order */
249 qsort(start
, entries
, sizeof(void *), &compare_R
);
252 /* safe all strings */
253 for (sipp
= start
; sipp
< stop
; sipp
++) {
254 (*sipp
)->b_keyword_name
[sizeof((*sipp
)->b_keyword_name
) - 1] = 0;
255 (*sipp
)->b_global_type
[sizeof((*sipp
)->b_global_type
) - 1] = 0;
256 (*sipp
)->b_global_name
[sizeof((*sipp
)->b_global_name
) - 1] = 0;
257 (*sipp
)->b_file_name
[sizeof((*sipp
)->b_file_name
) - 1] = 0;
258 (*sipp
)->b_debug_info
[sizeof((*sipp
)->b_debug_info
) - 1] = 0;
261 if (strcmp(keyword
, "sysinit") == 0)
263 else if (strcmp(keyword
, "sysuninit") == 0)
266 errx(EX_USAGE
, "Unknown keyword '%s'", keyword
);
276 struct sysinit_data
**sipp
;
279 snprintf(scratch_buf
, sizeof(scratch_buf
),
281 " * This file was automatically generated.\n"
282 " * Please do not edit.\n"
285 /* write out externals */
286 for (c
= 0, sipp
= start
; sipp
< stop
; c
++, sipp
++) {
287 if (strcmp((const char *)(*sipp
)->b_keyword_name
, keyword
))
289 if ((*sipp
)->dw_msb_value
== 0)
292 snprintf(scratch_buf
, sizeof(scratch_buf
),
293 "/* #%04u: %s entry at %s:%u */\n",
294 c
, (*sipp
)->b_debug_info
, (*sipp
)->b_file_name
,
295 (unsigned int)(*sipp
)->dw_file_line
);
297 do_write(output_file
, scratch_buf
);
299 snprintf(scratch_buf
, sizeof(scratch_buf
),
300 "extern %s %s;\n\n", (*sipp
)->b_global_type
,
301 (*sipp
)->b_global_name
);
303 do_write(output_file
, scratch_buf
);
306 snprintf(scratch_buf
, sizeof(scratch_buf
),
307 "const void *%s[] = {\n", struct_name
);
309 do_write(output_file
, scratch_buf
);
311 /* write out actual table */
312 for (c
= 0, sipp
= start
; sipp
< stop
; c
++, sipp
++) {
313 if (strcmp((const char *)(*sipp
)->b_keyword_name
, keyword
))
315 if ((*sipp
)->dw_msb_value
== 0)
318 snprintf(scratch_buf
, sizeof(scratch_buf
),
319 "\t&%s, /* #%04u */\n",
320 (*sipp
)->b_global_name
, (unsigned int)c
);
322 do_write(output_file
, scratch_buf
);
325 snprintf(scratch_buf
, sizeof(scratch_buf
),
326 "\t(const void *)0\n"
329 do_write(output_file
, scratch_buf
);