[PATCH v2] ruckus_fw_header: Add Ruckus Firmware builder for Ruckus R500 and others

Rafał Miłecki zajec5 at gmail.com
Mon Jan 3 02:28:21 PST 2022


On 3.12.2021 01:18, tusker at tusker.org wrote:
> From: Damien Mascord <tusker at tusker.org>
> 
> This image builder builds a tftp updatable binary for Ruckus hardware

Hey, I missed this patch, my suggestion would be to use something like
[PATCH firmware-utils V2]

Let me look at it now.

First git complains about some whitespaces:

Applying: ruckus_fw_header: Add Ruckus Firmware builder for Ruckus R500 and others
.git/rebase-apply/patch:97: trailing whitespace.
         char load_address[4] = {
.git/rebase-apply/patch:98: trailing whitespace.
                 0x80, 0x06, 0x00, 0x00 };
.git/rebase-apply/patch:110: trailing whitespace.
                 0x4f, 0x50, 0x45, 0x4e, 0x57, 0x52, 0x54, 0x31, 0x32, 0x33, 0x34, 0x35,
.git/rebase-apply/patch:118: trailing whitespace.
         char header4[4] = {
.git/rebase-apply/patch:120: trailing whitespace.
         char entry_point[4] = {
warning: squelched 13 whitespace errors
warning: 18 lines add whitespace errors.


> @@ -0,0 +1,258 @@
> +/*
> + * rucks_fw_header.c - partially based on OpenWrt's xorimage.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */

Please use SPDX header


> +int write_header(FILE *out, char* md5sum){
> +	// lzma kernel offset is ruckus header + uimage header = 160 + 64 = 224 = 0xE0
> +	char header1[12] = {
> +		0x52, 0x43, 0x4b, 0x53, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x6c, 0x37 };
> +	char load_address[4] = {	
> +		0x80, 0x06, 0x00, 0x00 };	
> +	char fakesize[4] = {
> +		0x01, 0x76, 0xd7, 0x5c };
> +	char header_postsize[4] = {
> +		0x60, 0x9a, 0x43, 0xd2 };
> +	char fakemd5[16] = {
> +		0x39, 0x17, 0x73, 0x56, 0xed, 0x87, 0x33, 0x9a, 0xe3, 0xe4, 0xff, 0xc9,
> +		0xee, 0xcd, 0xd2, 0x9c };
> +	char header2[4] = {
> +		0x00, 0x04, 0x66, 0x69 };
> +	//200.7.10.202.9 - OPENWRT12345678
> +	char fake_version[16] = {
> +		0x4f, 0x50, 0x45, 0x4e, 0x57, 0x52, 0x54, 0x31, 0x32, 0x33, 0x34, 0x35,
> +		0x36, 0x37, 0x38, 0x39 };
> +	char header3[48] = {
> +		0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +		0x7a, 0x66, 0x37, 0x37, 0x35, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
> +	//200.7.10.202.9 - OPENWRT12345678
> +	char header4[4] = {	
> +		0x00, 0x00, 0x00, 0x03 };
> +	char entry_point[4] = {	
> +		0x80, 0x06, 0x00, 0x00 };
> +	char header_postentry[28] = {
> +	    0x00, 0x00, 0x00, 0x01, 0x01, 0x76, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00,
> +	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	    0x00, 0x00, 0x00, 0x00 };

It's full of magic values, hard to maintain & hacky. Please use a packed
struct with proper width (u8 / u16 / u32) named fields. Fill them using
real values and helpers like cpu_to_le32 / cpu_to_be32.

Then fwrite whole struct at once.

Make function static.


> +void usage(void) __attribute__ (( __noreturn__ ));

Do we need that?


> +void usage(void)
> +{
> +	fprintf(stderr, "Usage: ruckus_fw_header [-i infile] [-o outfile] [-d]\n");
> +	exit(EXIT_FAILURE);
> +}

Static function


> +int main(int argc, char **argv)
> +{
> +	char buf[1];	/* keep this at 1k or adjust garbage calc below */
> +	FILE *in = stdin;
> +	FILE *out = stdout;
> +	char *ifn = NULL;
> +	char *ofn = NULL;
> +	int c;
> +	int v0, v1, v2;
> +	size_t n;
> +	int p_len, p_off = 0;
> +    uint8_t  md5sum[0x10];

Use tab for indent.


> +
> +	while ((c = getopt(argc, argv, "i:o:h")) != -1) {
> +		switch (c) {
> +			case 'i':
> +				ifn = optarg;
> +				break;
> +			case 'o':
> +				ofn = optarg;
> +				break;
> +			case 'h':
> +			default:
> +				usage();
> +		}
> +	}
> +	
> +	data_size = get_file_size(ifn);

Check returned value.
Maybe make that a local variable to keep code a bit cleaner.


> +	if (optind != argc || optind == 1) {
> +		fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
> +		usage();
> +	}
> +
> +	if (ifn && md5_file(ifn, md5sum)) {
> +		fprintf(stderr, "can not get md5sum for \"%s\"\n", ifn);
> +		usage();
> +	}
> +
> +	if (ifn && !(in = fopen(ifn, "r"))) {
> +		fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
> +		usage();
> +	}
> +
> +	if (ofn && !(out = fopen(ofn, "w"))) {
> +		fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
> +		usage();
> +	}
> +
> +	if (ofn && (write_header(out, md5sum))) {
> +		fprintf(stderr, "can not write header to \"%s\"\n", ofn);
> +		usage();
> +	}
> +
> +	while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
> +		if (n < sizeof(buf)) {
> +			if (ferror(in)) {
> +			FREAD_ERROR:
> +				fprintf(stderr, "fread error\n");
> +				return EXIT_FAILURE;
> +			}
> +		}
> +
> +		if (!fwrite(buf, n, 1, out)) {
> +		FWRITE_ERROR:
> +			fprintf(stderr, "fwrite error\n");
> +			return EXIT_FAILURE;
> +		}
> +	}
> +
> +	if (ferror(in)) {
> +		goto FREAD_ERROR;
> +	}
> +
> +	if (fflush(out)) {
> +		goto FWRITE_ERROR;
> +	}

It's much more common to keep failure path at the end of function.
Jumping into a conditional block inside a loop looks a bit hacky - even
if just to exit.

It also results in printing "fwrite error" on fflush() failure. A bit
misleading.


> +
> +	fclose(in);
> +	fclose(out);
> +
> +	return EXIT_SUCCESS;
> +}




More information about the openwrt-devel mailing list