[PATCH v2] ruckus_fw_header: Add Ruckus Firmware builder for Ruckus R500 and others
tusker at tusker.org
tusker at tusker.org
Thu Dec 2 16:18:32 PST 2021
From: Damien Mascord <tusker at tusker.org>
This image builder builds a tftp updatable binary for Ruckus hardware
Signed-off-by: Damien Mascord <tusker at tusker.org>
---
CMakeLists.txt | 1 +
src/ruckus_fw_header.c | 258 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 259 insertions(+)
create mode 100644 src/ruckus_fw_header.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f406520..c6fbf5c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,6 +88,7 @@ FW_UTIL(oseama src/md5.c "" "")
FW_UTIL(otrx "" "" "")
FW_UTIL(pc1crypt "" "" "")
FW_UTIL(ptgen src/cyg_crc32.c "" "")
+FW_UTIL(ruckus_fw_header src/md5.c "" "")
FW_UTIL(seama src/md5.c "" "")
FW_UTIL(sign_dlink_ru src/md5.c "" "")
FW_UTIL(spw303v "" "" "")
diff --git a/src/ruckus_fw_header.c b/src/ruckus_fw_header.c
new file mode 100644
index 0000000..aad3a81
--- /dev/null
+++ b/src/ruckus_fw_header.c
@@ -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
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "md5.h"
+
+#define BUF_SIZE 0x200
+static int data_size;
+
+static int get_file_size(char *name)
+{
+ struct stat st;
+ int res;
+
+ res = stat(name, &st);
+ if (res){
+ fprintf(stderr,"stat failed on %s", name);
+ return -1;
+ }
+
+ return st.st_size;
+}
+
+static int md5_file(const char *filename, uint8_t *dst)
+{
+ FILE *fp_src;
+ MD5_CTX ctx;
+ char buf[BUF_SIZE];
+ size_t bytes_read;
+
+ MD5_Init(&ctx);
+
+ fp_src = fopen(filename, "r+b");
+ if (!fp_src) {
+ return -1;
+ }
+ while (!feof(fp_src)) {
+ bytes_read = fread(&buf, 1, BUF_SIZE, fp_src);
+ MD5_Update(&ctx, &buf, bytes_read);
+ }
+ fclose(fp_src);
+
+ MD5_Final(dst, &ctx);
+
+ return 0;
+}
+
+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 };
+
+ if (!fwrite(header1, sizeof(header1), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(load_address, sizeof(load_address), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ u_int32_t ds = htonl(data_size);
+ fprintf(stdout, "data_size: %d\n", ds);
+ if (!fwrite(&ds, sizeof(ds), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(header_postsize, sizeof(header_postsize), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(md5sum, 0x10, 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(header2, sizeof(header2), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(fake_version, sizeof(fake_version), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(header3, sizeof(header3), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(fake_version, sizeof(fake_version), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(header4, sizeof(header4), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(entry_point, sizeof(entry_point), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!fwrite(header_postentry, sizeof(header_postentry), 1, out)) {
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+
+ return 0;
+}
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: ruckus_fw_header [-i infile] [-o outfile] [-d]\n");
+ exit(EXIT_FAILURE);
+}
+
+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];
+
+ 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);
+
+ 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;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
--
2.30.2
More information about the openwrt-devel
mailing list