Project

General

Profile

convert.sh

sucanjan@fit.cvut.cz, 06/23/2017 03:51 AM

Download (8.24 KB)

 
1
#!/bin/sh
2

    
3
# Copyright (c) 2017 The DragonFly Project. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions are
7
# met:
8
#
9
# Redistributions of source code must retain the above copyright notice,
10
# this list of conditions and the following disclaimer.
11
#
12
# Redistributions in binary form must reproduce the above copyright
13
# notice, this list of conditions and the following disclaimer in the
14
# documentation and/or other materials provided with the distribution.
15
#
16
# Neither the name of The DragonFly Project nor the names of its
17
# contributors may be used to endorse or promote products derived from
18
# this software without specific, prior written permission.
19
#
20
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS
21
# IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
# INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
30
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31
# DAMAGE.
32

    
33
# Prefixes for a files generated by parsing ISP driver C header file
34
# with firmware. For their meaning see the parse_isp_firmware_header()
35
# function info.
36
license_file="license"
37
name_file="name_"
38
info_file="info_"
39
data_file="data_"
40
# Prefix for a binary file for firmware binary data. The binary file
41
# contains output of sh execution of printf commands in "data_N" file.
42
binary_file="binary_"
43
# Suffix for output files which this script produces
44
firmware_suffix=".fw.uu"
45
# This string (and a number) will be added to the names of the other
46
# variants of one firmware to form a unique filenames for the script
47
# output files
48
variant_string=".variant_"
49

    
50
# Function usage: parse_isp_firmware_header FILE
51
#
52
#    FILE - Path to ISP driver C header file with firmware data.
53
#
54
# Result of this function are files containing parts of the header
55
# file and generated sh commands. One header file can contain multiple
56
# firmware images. Because of that, each file which contains image
57
# specific info has a number N appended to its name. N is integer
58
# number starting from 0. Files with the same N belongs to the same
59
# firmware image.
60
#
61
#    license - Firmware license.
62
#    name_N  - Image name. This will be the name of the final firmware .uu file.
63
#    info_N  - Comment blocks with info about firmware image.
64
#    data_N  - Printf calls that convert image words hex numbers to their
65
#              values. This file is intended to be executed by sh and the stdout
66
#              to be redirected to a file.
67
#
68
# NOTE: Resulting image words values will be in little-endian format.
69
parse_isp_firmware_header()
70
{
71
    awk '
72
# This function converts chars from "a" to "f" to decimal numbers from
73
# 10 to 15 respectively. Every other character is returned as is.
74
# Parameters "chars" and "char_array" are local variables.
75
function hex_alpha_to_dec(a, chars, char_array) {
76
  chars = "a,b,c,d,e,f"
77
  split(chars, char_array, ",")
78
  
79
  if (a ~ /[abcdef]/) {
80
     for (j = 1; ; ++j) {
81
       if (char_array[j] == a) {
82
         return (10 + j - 1)
83
       }
84
     }  
85
  } else {
86
    return a
87
  }
88
}
89

    
90
# This function converts two-digit hex number to decimal number.
91
# The input hex number is without "0x" prefix and "h" suffix.
92
# Parameters "a" and "b" are local variables.
93
function hex_to_dec(h, a, b) {
94
  h = tolower(h)
95
  a = hex_alpha_to_dec(substr(h, 1, 1))
96
  b = hex_alpha_to_dec(substr(h, 2, 1))
97
  return ((a * 16) + b)
98
} 
99

    
100
BEGIN {
101
  state = "license"
102
  license_file = "'"${license_file}"'"
103
  name_file = "'"${name_file}"'"
104
  info_file = "'"${info_file}"'"
105
  data_file = "'"${data_file}"'"
106
  image_number = 0
107
}
108

    
109
# Filter out file information line(s) (file path, version, date, author, ...)
110
/^\/\* \$.*\$ \*\// {
111
  next
112
}
113

    
114
# Print the first line of the license contained in one comment block
115
(state == "license") && /\/\*/ {
116
  print $0 > license_file
117
  state = "inside_license"
118
  next
119
}
120

    
121
# Print the last line of the license contained in one comment block
122
(state == "inside_license") && /\*\// {
123
  print $0 > license_file
124
  # License has been read, process comment blocks which contains info
125
  # about the next firmware
126
  state = "info"
127
  next
128
}
129

    
130
# Print lines inside the license comment block
131
(state == "inside_license") {
132
  print $0 > license_file
133
  next
134
}
135

    
136
# Print info text of the next firmware contained in one comment block
137
(state == "info") && /\/\*/,/\*\// {
138
  out = sprintf("%s%s", info_file, image_number);
139
  print $0 > out
140
  next
141
}
142

    
143
# Process array declaration line, get the name of the firmware and data type of
144
# array values 
145
/\[\] = \{/ {
146
  state = "array"
147
  split($0, decl)
148
  split(decl[4], name, "_risc_code")
149
  array_name = name[1]
150
  array_type = decl[3]
151
  
152
  if (array_type ~ /int16/) {
153
    # Data type of the array values is 16-bit 
154
    state = "data16"
155
  } else {
156
    # Data type of the array values is 32-bit 
157
    state = "data32"
158
  }
159
  # Save the firmware name
160
  out = sprintf("%s%s", name_file, image_number);
161
  printf "%s", array_name > out
162
  next
163
}
164

    
165
# Current array has ended, process the next one
166
((state == "data16") || ((state == "data32"))) && /\}/ {
167
  state = "info"
168
  image_number++
169
  next
170
}
171

    
172
# Process one line of array content definition
173
# Generate shell printf calls for the array values
174
(state == "data16") || (state == "data32") {
175
  gsub("[ \t]", "", $0)
176
  split($0, values, ",")
177

    
178
  for (i = 1; length(values[i]) > 0; ++i) {
179
     # Get the single bytes
180
     a = substr(values[i], 3, 2)
181
     b = substr(values[i], 5, 2)
182
     if (state == "data32") {
183
       c = substr(values[i], 7, 2)
184
       d = substr(values[i], 9, 2)     
185
     }
186
     # POSIX printf needs the number to be in octal format in the escape
187
     # sequence
188
     # Swap the bytes to be in little-endian format
189
     v = ""
190
     if (state == "data32") {
191
       v = "\\" sprintf("%o", hex_to_dec(d)) "\\" sprintf("%o", hex_to_dec(c))
192
     }
193
     v = v "\\" sprintf("%o", hex_to_dec(b)) "\\" sprintf("%o", hex_to_dec(a))
194
     out = sprintf("%s%s", data_file, image_number);
195
     printf "printf \"%s\"\n", v > out
196
  }
197
  next
198
}
199
' "$1"
200
}
201

    
202
# Check input file and its existence
203
if [ $# -ne 1 ]; then
204
    printf "Usage: $0 HEADER_FILE\n" >&2
205
    exit 1
206
elif [ ! -f "$1" ]; then
207
    printf "Error: file '$1' does not exists\n" >&2
208
    exit 1
209
fi
210

    
211
parse_isp_firmware_header "$1"
212

    
213
# Concatenate the files to form a firmware .uu files
214
image_number=0
215

    
216
while [ -f "${name_file}${image_number}" ]; do
217
    output_file="$(cat ${name_file}${image_number})"
218
    # Some ISP firmware header files (asm_2100.h) contains more
219
    # variants of the same firmware image. Append _var_M to the second
220
    # and the following image's names, where 1 <= M. Name of the first
221
    # image in the header file will get nothing appended.
222
    if [ -f "${output_file}${firmware_suffix}" ]; then
223
	# Find unused variant number	
224
	variant_number=1
225
	tmp_name="${output_file}${variant_string}${variant_number}"
226
	while [ -f "$tmp_name" ];do
227
	    variant_number=$((variant_number + 1))
228
    	    tmp_name="${output_file}${variant_string}${variant_number}"
229
	done
230
	# Add the suffix
231
	output_file="$tmp_name"
232
    fi
233
    output_file="${output_file}${firmware_suffix}"
234
    
235
    # Add the license
236
    cat "$license_file" > "$output_file"
237
    # Add the firmware information if it exists
238
    [ -f "${info_file}${image_number}" ] && \
239
        cat "${info_file}${image_number}" >> "$output_file"
240
    # Generate firmware binary data
241
    cat "${data_file}${image_number}" | sh > "${binary_file}${image_number}"
242
    # uuencode the data and add it to the output file
243
    uuencode "${binary_file}${image_number}" \
244
             "${binary_file}${image_number}" >> "$output_file"
245
    
246
    image_number=$((image_number + 1))
247
done
248

    
249
# Remove temporary files generated by parsing the ISP driver C header
250
# file with firmware data
251
eval rm -f \"${license_file}\"\*  \
252
     \"${name_file}\"\*  \
253
     \"${info_file}\"\*  \
254
     \"${data_file}\"\*  \
255
     \"${binary_file}\"\*