+ Changelog:
+ v2.3 - allow jffs by adding its magic number (0x8519)
+ added parameter option -i to ignore unknown magic numbers
+ v2.2 - fixed checksum byte calculation for other versions than 0x2019
+ fixed rare problem with padsize
+ updated info to stock firmware 2.00.20
+ fixed typos
+ v2.1 - used "wrt350n.bin" for the created image (closer to stock)
+ added option to create the image in two separate steps (-b / -z)
+ v2.0 - complete re-write
mtd_info mtd_uboot = { "u-boot", 0, 0, NULL, 0L, { 0, 0 } };
#define ROOTFS_END_OFFSET 0x00760000
mtd_info mtd_uboot = { "u-boot", 0, 0, NULL, 0L, { 0, 0 } };
#define ROOTFS_END_OFFSET 0x00760000
-#define ROOTFS_MIN_OFFSET 0x00700000 // should be filled up to here, to make sure that the zip file is big enough to pass the size check of the stock firmware
+#define ROOTFS_MIN_OFFSET 0x00640000 // should be filled up to here, to make sure that the zip file is big enough to pass the size check of the stock firmware
+ // 2.0.17: filled up to 0x00640000
+ // 2.0.19: filled up to 0x00670000
+ // 2.0.20: filled up to 0x00670000
// rootfs statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x0075FFE0 -n 16 "wrt350n.bin" ; echo -en "\n"
unsigned char product_id[] = { 0x00, 0x03 }; // seems to be a fixed value
unsigned char protocol_id[] = { 0x00, 0x00 }; // seems to be a fixed value
// rootfs statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x0075FFE0 -n 16 "wrt350n.bin" ; echo -en "\n"
unsigned char product_id[] = { 0x00, 0x03 }; // seems to be a fixed value
unsigned char protocol_id[] = { 0x00, 0x00 }; // seems to be a fixed value
unsigned char rootfs_unknown[] = { 0x90, 0xF7 }; // seems to be a fixed value
unsigned char sign[] = { 0x65, 0x52, 0x63, 0x4F, 0x6D, 0x4D, 0x00, 0x00 }; // eRcOmM
unsigned char rootfs_unknown[] = { 0x90, 0xF7 }; // seems to be a fixed value
unsigned char sign[] = { 0x65, 0x52, 0x63, 0x4F, 0x6D, 0x4D, 0x00, 0x00 }; // eRcOmM
0x00, 0x00, 0x00, 0x04,
0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D }; // sErCoMm
0x00, 0x00, 0x00, 0x04,
0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D }; // sErCoMm
unsigned char img_hdr[] = { 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, 0x10, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
unsigned char img_hdr[] = { 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, 0x10, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
exitcode = 1;
printf("parse_par_file: can not allocate %i bytes\n", (int) buffer_size);
break;
}
line = fgets(buffer, buffer_size, f_par);
exitcode = 1;
printf("parse_par_file: can not allocate %i bytes\n", (int) buffer_size);
break;
}
line = fgets(buffer, buffer_size, f_par);
case '#': // integer values
count = sscanf(line, "#%255s %i", string1, &value);
if (count != 2) {
case '#': // integer values
count = sscanf(line, "#%255s %i", string1, &value);
if (count != 2) {
addsize += KERNEL_CODE_OFFSET + mtd->offset + mtd->filesize; // get offset
lprintf(DEBUG, " padding offset 0x%08X length 0x%08X\n", addsize, padsize);
f_in = fopen(rand_filename, "rb");
addsize += KERNEL_CODE_OFFSET + mtd->offset + mtd->filesize; // get offset
lprintf(DEBUG, " padding offset 0x%08X length 0x%08X\n", addsize, padsize);
f_in = fopen(rand_filename, "rb");
memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET + 2], rootfs_unknown, 2);
memcpy(&buffer[KERNEL_CODE_OFFSET + SIGN_OFFSET], sign, 8); // eRcOmM
memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET + 2], rootfs_unknown, 2);
memcpy(&buffer[KERNEL_CODE_OFFSET + SIGN_OFFSET], sign, 8); // eRcOmM
- lprintf(DEBUG, "adding u-boot special data 1/2\n"); // ToDo: or after creating the checksum byte?
-// memcpy(&buffer[KERNEL_CODE_OFFSET + SN_OFF], sn, 12); // ToDo: find out what's this for?
-// memcpy(&buffer[KERNEL_CODE_OFFSET + PIN_OFF], pin, 8); // ToDo: find out what's this for?
-// memcpy(&buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF], node, 25); // ToDo: find out what's this for?
+ lprintf(DEBUG, "adding u-boot special data\n");
+// memcpy(&buffer[KERNEL_CODE_OFFSET + SN_OFF], sn, 12); // ToDo: currently zero, find out what's this for?
+// memcpy(&buffer[KERNEL_CODE_OFFSET + PIN_OFF], pin, 8); // ToDo: currently zero, find out what's this for?
+// memcpy(&buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF], node, 25); // ToDo: currently zero, find out what's this for?
+ memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET], pid, 70); // sErCoMm
+ memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET + 57], fw_version, 2);
}
// write bin file
if (!exitcode) {
lprintf(DEBUG, "writing file %s\n", bin_filename);
f_out = fopen(bin_filename, "wb");
}
// write bin file
if (!exitcode) {
lprintf(DEBUG, "writing file %s\n", bin_filename);
f_out = fopen(bin_filename, "wb");
- count = snprintf(buffer, buffer_size, "zip %s %s", zip_filename, bin_filename);
- if (count > -1 && count < buffer_size) {
+ count = snprintf(buffer, buffer_size, "zip \"%s\" \"%s\"", zip_filename, bin_filename);
+ if ((count > -1) && (count < buffer_size)) {
- if (!access(out_filename, F_OK)) { // if file already exists then check write access
- if (access(out_filename, W_OK)) {
- printf("No write access to output file %s\n", out_filename);
+ if (!access(img_filename, F_OK)) { // if file already exists then check write access
+ if (access(img_filename, W_OK)) {
+ printf("No write access to image file %s\n", img_filename);
- base_filename = strdup(base_filename);
- zip_filename = strrchr(base_filename, '.');
- if (zip_filename != NULL) {
- zip_filename[0] = 0;
- zip_filename = NULL; // clean up
+ base_filename = basename(img_filename);
+ if (!base_filename) {
+ printf("Image file is a directory\n");
+ exitcode = 1;
- // react on parameter problems or help request, and exit
- if ((exitcode != 0) || help) {
+ // check for mutually exclusive options
+ if ((onlybin) && (havezip)) {
+ printf("Option -b and -z are mutually exclusive\n");
+ exitcode = 1;
+ }
+
+ // react on option problems or help request, then exit
+ if ((exitcode) || (help)) {
- lprintf(DEBUG_LVL2, " verbosity: %i\n", verbosity);
- lprintf(DEBUG_LVL2, " program: %s\n", argv[0]);
+ lprintf(DEBUG_LVL2, " Verbosity: %i\n", verbosity);
+ lprintf(DEBUG_LVL2, " Program: %s\n", argv[0]);
- lprintf(DEBUG, "Parameter file: %s\n", par_filename);
- lprintf(DEBUG, "Output file: %s\n", out_filename);
- lprintf(DEBUG_LVL2, " basename: %s (%i)\n", base_filename, strlen(base_filename));
+ if (par_filename) {
+ lprintf(DEBUG, "Parameter file: %s\n", par_filename);
+ }
+ if (zip_filename) {
+ lprintf(DEBUG, "Zip file: %s\n", zip_filename);
+ }
+ if (img_filename) {
+ lprintf(DEBUG, "Image file: %s\n", img_filename);
+ }
- // output file
- f_out = fopen(out_filename, "w");
- if (f_out == NULL) {
- exitcode = errno;
- printf("Output file %s: %s\n", out_filename, strerror(exitcode));
+ // image file
+ if (img_filename) {
+ f_img = fopen(img_filename, "wb");
+ if (!f_img) {
+ exitcode = errno;
+ printf("Output file %s: %s\n", img_filename, strerror(exitcode));
+ }
lprintf(DEBUG, "parsing parameter file...\n");
exitcode = parse_par_file(f_par);
lprintf(DEBUG, "...done parsing file\n");
}
lprintf(DEBUG, "parsing parameter file...\n");
exitcode = parse_par_file(f_par);
lprintf(DEBUG, "...done parsing file\n");
}
- if (magic[0]) {
- if (mtd->magic[0] != magic[0] || mtd->magic[1] != magic[1]) {
- exitcode = 1;
- printf("mtd %s input file %s has wrong magic number (0x%02X%02X)\n", mtd->name, mtd->filename, mtd->magic[0], mtd->magic[1]);
+ magicerror = 0;
+ if (magiccheck) {
+ switch (i) {
+ case 1: // kernel
+ if (!(
+ ((mtd->magic[0] == 0x27) && (mtd->magic[1] == 0x05)) // uImage
+ )) {
+ magicerror = 1;
+ }
+ break;
+ case 2: // rootfs
+ if (!(
+ ((mtd->magic[0] == 0x68) && (mtd->magic[1] == 0x73)) // squashfs
+ || ((mtd->magic[0] == 0x85) && (mtd->magic[1] == 0x19)) // jffs
+ )) {
+ magicerror = 1;
+ }
+ break;
+ default:
+ magicerror = 1;
+ break;
+ }
+ if (magicerror) {
+ printf("mtd %s input file %s has unknown magic number (0x%02X%02X)", mtd->name, mtd->filename, mtd->magic[0], mtd->magic[1]);
+ if (ignoremagic) {
+ printf("...ignoring");
+ } else {
+ exitcode = 1;
+ }
+ printf("\n");
- if (!exitcode && par_filename != NULL) {
- // create bin name from basename
- bin_filename = malloc(strlen(base_filename)+10);
- sprintf(bin_filename, "%s.bin", base_filename);
+ if ((!exitcode) && (par_filename)) {
+ bin_filename = "wrt350n.bin";
- if (!exitcode && zip_filename == NULL) {
- // create zip name from basename
- zip_filename = malloc(strlen(base_filename)+10);
- sprintf(zip_filename, "%s.zip", base_filename);
+ if ((!exitcode) && (!onlybin) && (!zip_filename)) {
+ zip_filename = "wrt350n.zip";