|
#!/bin/sh
|
|
|
|
# Copyright (c) 2017 The DragonFly Project. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# Neither the name of The DragonFly Project nor the names of its
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific, prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS
|
|
# IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
# INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
|
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
# DAMAGE.
|
|
|
|
# Prefixes for a files generated by parsing ISP driver C header file
|
|
# with firmware. For their meaning see the parse_isp_firmware_header()
|
|
# function info.
|
|
license_file="license"
|
|
name_file="name_"
|
|
info_file="info_"
|
|
data_file="data_"
|
|
# Prefix for a binary file for firmware binary data. The binary file
|
|
# contains output of sh execution of printf commands in "data_N" file.
|
|
binary_file="binary_"
|
|
# Suffix for output files which this script produces
|
|
firmware_suffix=".fw.uu"
|
|
# This string (and a number) will be added to the names of the other
|
|
# variants of one firmware to form a unique filenames for the script
|
|
# output files
|
|
variant_string=".variant_"
|
|
|
|
# Function usage: parse_isp_firmware_header FILE
|
|
#
|
|
# FILE - Path to ISP driver C header file with firmware data.
|
|
#
|
|
# Result of this function are files containing parts of the header
|
|
# file and generated sh commands. One header file can contain multiple
|
|
# firmware images. Because of that, each file which contains image
|
|
# specific info has a number N appended to its name. N is integer
|
|
# number starting from 0. Files with the same N belongs to the same
|
|
# firmware image.
|
|
#
|
|
# license - Firmware license.
|
|
# name_N - Image name. This will be the name of the final firmware .uu file.
|
|
# info_N - Comment blocks with info about firmware image.
|
|
# data_N - Printf calls that convert image words hex numbers to their
|
|
# values. This file is intended to be executed by sh and the stdout
|
|
# to be redirected to a file.
|
|
#
|
|
# NOTE: Resulting image words values will be in little-endian format.
|
|
parse_isp_firmware_header()
|
|
{
|
|
awk '
|
|
# This function converts chars from "a" to "f" to decimal numbers from
|
|
# 10 to 15 respectively. Every other character is returned as is.
|
|
# Parameters "chars" and "char_array" are local variables.
|
|
function hex_alpha_to_dec(a, chars, char_array) {
|
|
chars = "a,b,c,d,e,f"
|
|
split(chars, char_array, ",")
|
|
|
|
if (a ~ /[abcdef]/) {
|
|
for (j = 1; ; ++j) {
|
|
if (char_array[j] == a) {
|
|
return (10 + j - 1)
|
|
}
|
|
}
|
|
} else {
|
|
return a
|
|
}
|
|
}
|
|
|
|
# This function converts two-digit hex number to decimal number.
|
|
# The input hex number is without "0x" prefix and "h" suffix.
|
|
# Parameters "a" and "b" are local variables.
|
|
function hex_to_dec(h, a, b) {
|
|
h = tolower(h)
|
|
a = hex_alpha_to_dec(substr(h, 1, 1))
|
|
b = hex_alpha_to_dec(substr(h, 2, 1))
|
|
return ((a * 16) + b)
|
|
}
|
|
|
|
BEGIN {
|
|
state = "license"
|
|
license_file = "'"${license_file}"'"
|
|
name_file = "'"${name_file}"'"
|
|
info_file = "'"${info_file}"'"
|
|
data_file = "'"${data_file}"'"
|
|
image_number = 0
|
|
}
|
|
|
|
# Filter out file information line(s) (file path, version, date, author, ...)
|
|
/^\/\* \$.*\$ \*\// {
|
|
next
|
|
}
|
|
|
|
# Print the first line of the license contained in one comment block
|
|
(state == "license") && /\/\*/ {
|
|
print $0 > license_file
|
|
state = "inside_license"
|
|
next
|
|
}
|
|
|
|
# Print the last line of the license contained in one comment block
|
|
(state == "inside_license") && /\*\// {
|
|
print $0 > license_file
|
|
# License has been read, process comment blocks which contains info
|
|
# about the next firmware
|
|
state = "info"
|
|
next
|
|
}
|
|
|
|
# Print lines inside the license comment block
|
|
(state == "inside_license") {
|
|
print $0 > license_file
|
|
next
|
|
}
|
|
|
|
# Print info text of the next firmware contained in one comment block
|
|
(state == "info") && /\/\*/,/\*\// {
|
|
out = sprintf("%s%s", info_file, image_number);
|
|
print $0 > out
|
|
next
|
|
}
|
|
|
|
# Process array declaration line, get the name of the firmware and data type of
|
|
# array values
|
|
/\[\] = \{/ {
|
|
state = "array"
|
|
split($0, decl)
|
|
split(decl[4], name, "_risc_code")
|
|
array_name = name[1]
|
|
array_type = decl[3]
|
|
|
|
if (array_type ~ /int16/) {
|
|
# Data type of the array values is 16-bit
|
|
state = "data16"
|
|
} else {
|
|
# Data type of the array values is 32-bit
|
|
state = "data32"
|
|
}
|
|
# Save the firmware name
|
|
out = sprintf("%s%s", name_file, image_number);
|
|
printf "%s", array_name > out
|
|
next
|
|
}
|
|
|
|
# Current array has ended, process the next one
|
|
((state == "data16") || ((state == "data32"))) && /\}/ {
|
|
state = "info"
|
|
image_number++
|
|
next
|
|
}
|
|
|
|
# Process one line of array content definition
|
|
# Generate shell printf calls for the array values
|
|
(state == "data16") || (state == "data32") {
|
|
gsub("[ \t]", "", $0)
|
|
split($0, values, ",")
|
|
|
|
for (i = 1; length(values[i]) > 0; ++i) {
|
|
# Get the single bytes
|
|
a = substr(values[i], 3, 2)
|
|
b = substr(values[i], 5, 2)
|
|
if (state == "data32") {
|
|
c = substr(values[i], 7, 2)
|
|
d = substr(values[i], 9, 2)
|
|
}
|
|
# POSIX printf needs the number to be in octal format in the escape
|
|
# sequence
|
|
# Swap the bytes to be in little-endian format
|
|
v = ""
|
|
if (state == "data32") {
|
|
v = "\\" sprintf("%o", hex_to_dec(d)) "\\" sprintf("%o", hex_to_dec(c))
|
|
}
|
|
v = v "\\" sprintf("%o", hex_to_dec(b)) "\\" sprintf("%o", hex_to_dec(a))
|
|
out = sprintf("%s%s", data_file, image_number);
|
|
printf "printf \"%s\"\n", v > out
|
|
}
|
|
next
|
|
}
|
|
' "$1"
|
|
}
|
|
|
|
# Check input file and its existence
|
|
if [ $# -ne 1 ]; then
|
|
printf "Usage: $0 HEADER_FILE\n" >&2
|
|
exit 1
|
|
elif [ ! -f "$1" ]; then
|
|
printf "Error: file '$1' does not exists\n" >&2
|
|
exit 1
|
|
fi
|
|
|
|
parse_isp_firmware_header "$1"
|
|
|
|
# Concatenate the files to form a firmware .uu files
|
|
image_number=0
|
|
|
|
while [ -f "${name_file}${image_number}" ]; do
|
|
output_file="$(cat ${name_file}${image_number})"
|
|
# Some ISP firmware header files (asm_2100.h) contains more
|
|
# variants of the same firmware image. Append _var_M to the second
|
|
# and the following image's names, where 1 <= M. Name of the first
|
|
# image in the header file will get nothing appended.
|
|
if [ -f "${output_file}${firmware_suffix}" ]; then
|
|
# Find unused variant number
|
|
variant_number=1
|
|
tmp_name="${output_file}${variant_string}${variant_number}"
|
|
while [ -f "$tmp_name" ];do
|
|
variant_number=$((variant_number + 1))
|
|
tmp_name="${output_file}${variant_string}${variant_number}"
|
|
done
|
|
# Add the suffix
|
|
output_file="$tmp_name"
|
|
fi
|
|
output_file="${output_file}${firmware_suffix}"
|
|
|
|
# Add the license
|
|
cat "$license_file" > "$output_file"
|
|
# Add the firmware information if it exists
|
|
[ -f "${info_file}${image_number}" ] && \
|
|
cat "${info_file}${image_number}" >> "$output_file"
|
|
# Generate firmware binary data
|
|
cat "${data_file}${image_number}" | sh > "${binary_file}${image_number}"
|
|
# uuencode the data and add it to the output file
|
|
uuencode "${binary_file}${image_number}" \
|
|
"${binary_file}${image_number}" >> "$output_file"
|
|
|
|
image_number=$((image_number + 1))
|
|
done
|
|
|
|
# Remove temporary files generated by parsing the ISP driver C header
|
|
# file with firmware data
|
|
eval rm -f \"${license_file}\"\* \
|
|
\"${name_file}\"\* \
|
|
\"${info_file}\"\* \
|
|
\"${data_file}\"\* \
|
|
\"${binary_file}\"\*
|