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. 36license_file="license" 37name_file="name_" 38info_file="info_" 39data_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. 42binary_file="binary_" 43# Suffix for output files which this script produces 44firmware_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 48variant_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. 69parse_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. 75function 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. 93function 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 100BEGIN { 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 203if [ $# -ne 1 ]; then 204 printf "Usage: $0 HEADER_FILE\n" >&2 205 exit 1 206elif [ ! -f "$1" ]; then 207 printf "Error: file '$1' does not exists\n" >&2 208 exit 1 209fi 210 211parse_isp_firmware_header "$1" 212 213# Concatenate the files to form a firmware .uu files 214image_number=0 215 216while [ -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)) 247done 248 249# Remove temporary files generated by parsing the ISP driver C header 250# file with firmware data 251eval rm -f \"${license_file}\"\* \ 252 \"${name_file}\"\* \ 253 \"${info_file}\"\* \ 254 \"${data_file}\"\* \ 255 \"${binary_file}\"\* 256