summaryrefslogtreecommitdiffstats
path: root/tools/firmware-utils/src/bixutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/firmware-utils/src/bixutil.c')
-rw-r--r--tools/firmware-utils/src/bixutil.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/tools/firmware-utils/src/bixutil.c b/tools/firmware-utils/src/bixutil.c
new file mode 100644
index 000000000..6e7dcd479
--- /dev/null
+++ b/tools/firmware-utils/src/bixutil.c
@@ -0,0 +1,188 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define RTL_PRODUCT_MAGIC1 0x59a0e842
+#define SQUASH_MAGIC 0x73717368
+#define RTL_IMAGE_VERSION 1
+#define RTL_IMAGE_TYPE_RDIR 0xb162
+#define RTL_IMAGE_TYPE_BOOT 0xea43
+#define RTL_IMAGE_TYPE_RUN 0x8dc9
+#define RTL_IMAGE_TYPE_KFS 0xd92f
+#define RTL_IMAGE_TYPE_CCFG 0x2a05
+#define RTL_IMAGE_TYPE_DCFG 0x6ce8
+#define RTL_IMAGE_TYPE_LOG 0xc371
+
+#define ENDIAN_SWITCH32(x) (((x) >> 24) | \
+ (((x) >> 8) & 0xFF00) | \
+ (((x) << 8) & 0xFF0000) | \
+ (((x) << 24) &0xFF000000))
+#define ENDIAN_SWITCH16(x) ((((x) >> 8) & 0xFF) | \
+ (((x) << 8) & 0xFF00))
+
+
+struct image_header {
+ u_int32_t magic1;
+ u_int16_t type;
+ u_int8_t ver;
+ u_int8_t align1;
+ u_int16_t year;
+ u_int8_t mon;
+ u_int8_t day;
+ u_int8_t hour;
+ u_int8_t min;
+ u_int8_t sec;
+ u_int8_t align2;
+ u_int32_t len;
+ u_int16_t align3;
+ u_int8_t icsum;
+ u_int8_t hcsum;
+};
+
+void print_header(struct image_header *h)
+{
+ printf("Magic1: 0x%08x\n", ENDIAN_SWITCH32(h->magic1));
+ printf("Type: 0x%04x\n", ENDIAN_SWITCH16(h->type));
+ printf("Version: %d\n", h->ver);
+ printf("Built: %04d-%02d-%02d %02d:%02d:%02d\n",
+ ENDIAN_SWITCH16(h->year), h->mon, h->day, h->hour,
+ h->min, h->sec);
+ printf("Length: %ld\n", ENDIAN_SWITCH32(h->len));
+ printf("Checksums: 0x%02x (header), 0x%02x (image)\n",
+ h->hcsum, h->icsum);
+}
+
+void *do_mmap(char *filename, int size, int readonly)
+{
+ int fd;
+ int openflags = O_RDWR | O_CREAT | O_TRUNC;
+ int protflags = PROT_READ | PROT_WRITE;
+ void *ptr;
+ struct stat st;
+
+ if (readonly) {
+ openflags = O_RDONLY;
+ protflags = PROT_READ;
+ }
+
+ if (!size) {
+ if (!readonly)
+ goto failed;
+ if (stat(filename, &st) != 0) {
+ perror("stat failed");
+ goto failed;
+ }
+ size = st.st_size;
+ }
+
+ if (!size)
+ goto failed;
+
+ if ((fd = open(filename, openflags, 0644)) == -1) {
+ perror("open failed");
+ goto failed;
+ }
+
+ if (!readonly)
+ ftruncate(fd, size);
+
+ ptr = mmap(0, size, protflags, MAP_SHARED, fd, 0);
+ if (ptr == MAP_FAILED) {
+ perror("mmap failed");
+ goto mmap_failed;
+ }
+
+ return ptr;
+
+mmap_failed:
+ close(fd);
+failed:
+ return NULL;
+}
+
+int write_image(char *kernel, char *outfile)
+{
+ unsigned char type;
+ unsigned long ksize, padded;
+ unsigned long i;
+ unsigned char ch, *src, *dst;
+ struct stat st;
+ struct image_header *h;
+ time_t tt;
+ struct tm *ut;
+
+ tt = time(NULL);
+ ut = localtime(&tt);
+
+ if (stat(kernel, &st) != 0)
+ error(-1, "stat %s failed", kernel);
+ ksize = st.st_size;
+
+ padded = sizeof(struct image_header) +
+ ksize + ksize % 4; /* fs starts 32-bit aligned (?check) */
+
+ h = (struct image_header *)do_mmap(outfile, padded, 0);
+ if (!h)
+ return -1;
+
+ memset(h, 0, sizeof(struct image_header));
+
+ dst = (unsigned char *)((unsigned)h + sizeof(struct image_header));
+ src = (unsigned char *)do_mmap(kernel, ksize, 1);
+ if (!src)
+ return -1;
+
+ for (i = 0; i < ksize; i++) {
+ dst[i] = src[i];
+ h->icsum ^= src[i];
+ }
+
+ for (i = 0; i < ksize % 4; i++)
+ dst[ksize + i] = 0;
+
+ munmap(src, ksize);
+
+ h->magic1 = ENDIAN_SWITCH32(RTL_PRODUCT_MAGIC1);
+ h->type = ENDIAN_SWITCH16(RTL_IMAGE_TYPE_RUN);
+ h->ver = RTL_IMAGE_VERSION;
+ h->year = ENDIAN_SWITCH16(ut->tm_year + 1900);
+ h->mon = ut->tm_mon + 1;
+ h->day = ut->tm_mday;
+ h->hour = ut->tm_hour;
+ h->min = ut->tm_min;
+ h->sec = ut->tm_sec;
+ h->len = ENDIAN_SWITCH32(padded - sizeof(struct image_header));
+
+ for (i = 0; i < (sizeof(struct image_header) - 1); i++)
+ h->hcsum ^= ((unsigned char *)&h)[i];
+ munmap(h, padded);
+ return 0;
+}
+
+void usage(void)
+{
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3) usage();
+
+ printf("%d\n", sizeof(struct image_header));
+ if (!strncmp(argv[1], "info", 4)) {
+ print_header((struct image_header *)do_mmap(argv[2],
+ 0, 1));
+ } else if (!strncmp(argv[1], "pack", 4)) {
+ write_image(argv[2], argv[3]);
+ } else {
+ usage();
+ }
+
+ return 0;
+}