Luxul XBR-4500: Upgrading OpenWrt when there is no sysupgrade image

Hi

I've tried reading around but so far come up empty handed so was wondering if someone can point me in the right direction.

I have OpenWRT 19.07.7 installed on a Luxul XBR-4500 and I'm looking at upgrading 21.02. I'm trying to figure out how go about the upgrade when there's no sysupgrade image at https://downloads.openwrt.org/releases/21.02.1/targets/bcm53xx/generic/

The image https://downloads.openwrt.org/releases/21.02.1/targets/bcm53xx/generic/openwrt-21.02.1-bcm53xx-generic-luxul_xbr-4500-squashfs.lxl does not include "factory" in the name so does mean it can be used for initial install and upgrade?

If more detail or clarification is needed just let me know.

Thanks
Phillip

After more reading and looking at BINs and TRXs for other devices my understanding is now (oddly enough what I had previously read)

To produce a TRX from a BIN (that's for initial install) all you need to do is strip the first 32 (0x20) octets ie. dd bs=1 skip=32 if=/tmp/firmware.bin of=/tmp/firmware.trx

Though, as noted on numerous pages, this approach for generating the upgrade package is not recommended due to the likelihood of bricking the device if the individual isn't an expert.

In the case of Luxul devices there doesn't currently appear to be any packages specifically built for upgrading, so for now the stripping approach appears to be the only option.

Where the manufacturer is Luxul and device is XBR-4500, to provide some certainty to the user that the file they're stripping ought to subsequently produce a valid TRX image I've composed the following oneliner (yet to be tested) I'm interested in peoples feedback if this looks correct. Once confirmed I'll look at adding it to the devices wiki page.

# Produce TRX from BIN
#
# Confirm the following checks out for BIN image
#  - manufacturer's signature ie. LXL# at offset 0 (0x0)
#  - device's model ie. XBR-4500 at offset 16 (0x10)
#  - TRX begins at expected location ie. HDR0 at offset 32 (0x20)
# also, TRX_IMAGE must not be blank
# if so strip the manufacturer's details so we just have the TRX

BIN_IMAGE=/tmp/firmware.bin; TRX_IMAGE=/tmp/firmware.trx; [ "$(dd bs=1 count=4 if=${BIN_IMAGE} 2> /dev/null)" = "LXL#" ] && [ "$(dd bs=1 skip=16 count=8 if=${BIN_IMAGE} 2> /dev/null)" = "XBR-4500" ] && [ "$(dd bs=1 skip=32 count=4 if=${BIN_IMAGE} 2> /dev/null)" = "HDR0" ] && [ -n "${TRX_IMAGE}" ] && echo "Attempting to strip ${BIN_IMAGE}" && dd bs=1 skip=32 if=${BIN_IMAGE} of=${TRX_IMAGE} && echo "Produced ${TRX_IMAGE} from stripped ${BIN_IMAGE}"

Here's the oneliner for then flashing the device with the TRX

# Flash device with TRX
#
# Confirm the following checks out for TRX image
#  - TRX image has expected magic number ie. HDR0 at offset 0 (0x0)
# if so apply to device's firmware

TRX_IMAGE=/tmp/firmware.trx; [ "$(dd bs=1 count=4 if=${TRX_IMAGE} 2> /dev/null)" = "HDR0" ] && echo "Attempting to apply ${TRX_IMAGE} to firmware" && mtd -r write "${TRX_IMAGE}" firmware && echo "${TRX_IMAGE} firmware has been applied"

I was also interested to see what I could do to verify the 32-Bit CRC in the TRX header checks out against the associated file content, binwalk presumably checks the CRC but for whatever reason I wrote this anyways

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>

uint32_t crc32buf(unsigned char *buf, size_t len);
void hexDump(char *desc, void *addr, int len);

int main(int argc, char **argv)
{
  FILE *in;
  unsigned char *buf;
  size_t n;
  int exitcode;
  bool debug = (argc > 2 && strncmp(argv[2], "debug", 5) == 0);
  long fsize;
  uint32_t crc32;
  unsigned char crc32Str[4];

  if (argc < 2)
  {
    fprintf(stderr, "A file name must be provided\n");
    return 1;
  }

  if (debug) fprintf(stdout, "reading from file: %s\n", argv[1]);

  if (!(in = fopen(argv[1], "rb")))
  {
    fprintf(stderr, "problem opening file: %s\n", argv[1]);
    return 2;
  }

  fseek(in, 0, SEEK_END);
  fsize = ftell(in);
  fseek(in, 0, SEEK_SET);

  if (!(buf = malloc(fsize)))
  {
    fprintf(stderr, "malloc failed\n");
    return 3;
  }

  n = fread(buf, 1, fsize, in);
  fclose(in);
  if (n != fsize)
  {
    fprintf(stderr, "failed to read entire file: %s\n", argv[1]);
    return 4;
  }

  if (debug) hexDump("contents of file", buf, n);

  if (!(buf[0] == 'H' &&
        buf[1] == 'D' &&
        buf[2] == 'R' &&
        buf[3] == '0'))
  {
    fprintf(stderr, "TRX magic number not found, not proceeding with CRC calculation\n");
    return 5;
  }

  crc32 = crc32buf(buf + 12, n - 12);
  memcpy(crc32Str, &crc32, 4);

  if (debug) hexDump("calculated 32-Bit CRC", crc32Str, 4);

  if (crc32Str[0] == buf[8] &&
      crc32Str[1] == buf[9] &&
      crc32Str[2] == buf[10] &&
      crc32Str[3] == buf[11])
  {
    fprintf(stdout, "Checksums match: %02x%02x%02x%02x\n", buf[8], buf[9], buf[10], buf[11]);
    exitcode = 0;
  }
  else
  {
    fprintf(stdout, "Checksums do not match\n");
    fprintf(stdout, "Calculated checksum: %02x%02x%02x%02x\n", crc32Str[0], crc32Str[1], crc32Str[2], crc32Str[3]);
    fprintf(stdout, "Checksum read from file: %02x%02x%02x%02x\n", buf[8], buf[9], buf[10], buf[11]);
    exitcode = 6;
  }

  free(buf);

  return exitcode;
}

/* Following CRC calculation code sourced from

   https://git.archive.openwrt.org/?p=14.07/openwrt.git;a=blob;f=tools/firmware-utils/src/trx.c;h=aa1f5be4b65b66ac9a1a48d7304d9bef131080e1;hb=HEAD#l69
 */

static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))

uint32_t crc32buf(unsigned char *buf, size_t len)
{
  uint32_t crc;

  crc = 0xFFFFFFFF;

  for (; len; --len, ++buf)
  {
    crc = UPDC32(*buf, crc);
  }

  return crc;
}

/* Following hexDump function sourced from

   https://gist.github.com/domnikl/af00cc154e3da1c5d965
 */

void hexDump(char *desc, void *addr, int len)
{
  int i;
  unsigned char buff[17];
  unsigned char *pc = (unsigned char*)addr;

  // Output description if given.
  if (desc != NULL)
    printf("%s:\n", desc);

  // Process every byte in the data.
  for (i = 0; i < len; i++)
  {
    // Multiple of 16 means new line (with line offset).
    if ((i % 16) == 0)
    {
      // Just don't print ASCII for the zeroth line.
      if (i != 0)
        printf("  %s\n", buff);

      // Output the offset.
      printf("  %04x ", i);
    }

    // Now the hex code for the specific character.
    printf(" %02x", pc[i]);

    // And store a printable ASCII character for later.
    if ((pc[i] < 0x20) || (pc[i] > 0x7e))
      buff[i % 16] = '.';
    else
      buff[i % 16] = pc[i];
    buff[(i % 16) + 1] = '\0';
  }

  // Pad out last line if not exactly 16 characters.
  while ((i % 16) != 0)
  {
    printf("   ");
    i++;
  }

  // And print the final ASCII bit.
  printf("  %s\n", buff);
}

Hi I just flashed an ABR-4500 (v21.02.3) which is the same router but with the ports on the back.

Did you ever try your workaround for sysupgrade?

Hi

Thanks for letting me know that.

To alay my concerns I had an XBR-4500 modded to include a header on the boards UART vias. This has meant I’ve been able to confirm what the recovery procedure is when you perform a bad flash, in brief the Broadcom CFE includes recovery procedures (not yet tested out and I’m talking from memory)

I’m moving at glacial speeds on the project as it’s turned in to much more than flashing a router :slightly_smiling_face: I’ve gone down the road of a 18U rack, which isn’t big enough to fit my dev / modded XBR so that is making its way into a 4U but it doesn’t currently have rack ears.

So long story short, thank you for letting me know that and I plan at some stage to write up what I find... it’s part of the reason I’m building this monstrosity.

Phillip

@phi thanks for the reply.

I'm sure I have extra luxul router rack ears laying around.. if you want a set send me a msg. if you want to mount it instead of getting a shelf.

Targets I maintain / develop (bcm47xx, bcm53xx and bcm4908) don't require OpenWrt-custom sysupgrade images. It's a single image that can be used for both:

  1. Initial installation (from vendor custom firmware)
  2. OpenWrt's sysupgrade.

So worry not - just use the available firmware image.

OpenWrt's sysupgrade on those targets can be used for both:

  1. Reverting to vendor firmware
  2. Upgrading OpenWrt

I believe / hope it's actually a simpler & easier solution. Get image and flash it. Don't worry about vendor vs. OpenWrt, factory vs. sysupgrade.

1 Like

Thanks Rafał

1 Like

@rmilecki Great news, I'm glad you saw this thread! I had no idea those targets are an exception to the don't flash factory images as sysupgrades. Thank you for the development and maintaining!

@phi The ABR-4500 I have is in production in the field so I'm not sure when I can get to it to upgrade. Do you want to do one that you have in inventory?

Hi @account4538

I love your wording and just that alone is enough for me to say hell yes. It’s a bit of a mad house at the moment, perhaps I’ll explain over PM some time but it’d be my pleasure to confirm the precise procedure and eliminate any concern over bricking.

Phillip

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.