"Manually" creating RCW for LS1012A - Generating the CRC32

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

"Manually" creating RCW for LS1012A - Generating the CRC32

2,727 Views
hardsoft
Contributor II

I don't seem to be able to find the right combination of settings to generate the CRC32 checksum for a self-modified RCW. But I have seen posts to this community that suggest this should not be hard. Can someone tell me how to generate the correct CRC32 value using e.g. python or something else?. I looked through the default RCWs in the SDK for LS1012A-FRDM and LS1012A-RDB. They seem, in contrast to what QCVS creates, to follow the recommendation to let the RCW data be directly followed by a CRC check command:

00000000: 0001 ee01 55aa 55aa 0000 0000 0800 0008  ....U.U......... 
00000010: 0000 0000 0000 0000 0c00 00c0 0000 0835  ...............5 
00000020: 0018 0000 0000 0040 0000 0000 0000 0000  .......@........ 
00000030: 7145 0100 0000 0000 20a1 c218 0000 0000  qE...... ....... 
00000040: 0000 0000 9600 0000 0000 1040 0406 5709  ...........@..W. 
00000050: 0000 1050 5c01 5709 0000 0000 0006 5709  ...P\.W.......W. 
00000060: 9c00 0000 1804 5709 8028 5000 dc08 ea09  ......W..(P..... 
00000070: 204e 1080 0013 ea09 0000 0100 001a ee09   N.............. 
00000080: 0002 0000 5801 5709 0100 0000 1400 4c89  ....X.W.......L. 
00000090: 0c40 0f00 0000 5509 0861 0040 058e c915  .@....U..a.@....

The documentation seems to be rather clear: The CRC includes all bytes before the CRC check command using CRC32 default poly and a start value of 0xffff_ffff. But even with swapping bytes to and fro, I cannot recreate that checksum value. Neither the one following the RCW nor the one at the end.

Labels (1)
Tags (1)
0 Kudos
6 Replies

2,046 Views
steffendedekind
Contributor II

Solved by look at the (open) source from :

https://github.com/qoriq-open-source/rcw

Take a look into the rcw.py script - there the checksum algorithm is placed:

# Python's binascii.crc32() function uses a different algorithm to calculate
# the CRC, so we need to do it manually.  The polynomial value is 0x04c11db7.
# Python integers can be larger than 32 bits, so we have to "& 0xffffffff"
# to keep the value within a 32-bit range.  The CRC algorithm depends on this.
# Otherwise, some calculations may overflow.
def crc32(data):
    # Calculate the CRC table
    table = []
    for i in range(256):
        mask = i << 24
        for j in range(8):
            if mask & 0x80000000:
                mask = (mask << 1) ^ 0x04c11db7;
            else:
                mask <<= 1;
        table.append(mask & 0xffffffff)

    crc = 0xffffffff
    for i in data:
        crc = (crc << 8) ^ table[(crc >> 24) ^ ord(i)]
        crc = crc & 0xffffffff

    return crc

This can be easily used - or better use the whole rcw.py script. It allows you to maintain your RCW configurations in a readable format instead of storing a bunch of binaries. However you can took your binary and calculate the crc with the funtion from above. Take care to resprect endianess and also add the checksum command. For my system (LS1046A) I have to pass:

0x55AA55AA
0x0001EE01

...... (rcw + pbi) ....

0x40006108

Doing this crc32() calculates the correct checksum to be appended.

0 Kudos

2,046 Views
steffendedekind
Contributor II

Hi,

I have the same problem (with LS1046). I trying to calculate the checksum which is placed at the end of PBL data - no success yet.

For testing I took an existing rcw-pbl.bin like this one:

00000000 00 01 ee 01 55 aa 55 aa 00 00 00 0a 0c 00 10 0c |....U.U.........|
00000010 00 00 00 00 00 00 00 00 1e a0 c0 00 88 88 00 00 |................|
00000020 00 00 00 c1 00 50 02 40 00 00 00 00 00 00 00 00 |.....P.@........|
00000030 fc 28 03 00 00 00 00 00 02 23 20 01 04 41 00 00 |.(.......# ..A..|
00000040 01 00 00 00 96 00 00 00 00 00 10 50 5c 01 57 09 |...........P\.W.|
00000050 00 00 00 00 00 06 57 09 00 00 10 40 04 06 57 09 |......W....@..W.|
00000060 10 e0 00 00 78 01 57 09 08 00 00 00 00 00 18 09 |....x.W.........|
00000070 9e 00 00 00 18 04 57 09 9e 00 00 00 1c 04 57 09 |......W.......W.|
00000080 9e 00 00 00 20 04 57 09 20 4e 10 80 00 13 eb 09 |.... .W. N......|
00000090 80 28 50 00 dc 08 eb 09 00 08 00 00 c0 00 ee 09 |.(P.............|
000000a0 00 03 00 00 58 01 57 09 00 80 04 01 90 08 40 89 |....X.W.......@.|
000000b0 00 80 04 01 90 08 50 89 00 80 04 01 90 08 60 89 |......P.......`.|
000000c0 00 02 00 00 58 01 57 09 01 00 3f 00 00 00 10 89 |....X.W...?.....|
000000d0 0c 40 0f 00 00 00 55 09 08 61 00 40 fe 0e 6b b3 |.@....U..a.@..k.|
000000e0

So I took bytes 0 to D7 as bytearray in python and tried to calculate the checksum like 0xfe0e6bb3 (or endian swapped).

I tried any combination of endian conversion and/or quad swap before calculating the crc32 (binascii module was used) but never was able to reproduce the checksum.

I also tried to search in *.tcl and *.py scripts from the PBL tool - but did not found a good hint.

Edit:

Today I checked sources from https://github.com/qoriq-open-source
In "u-boot" there is an implementation in tools/pbl_crc32.c

In "rcw" there is an implementation in rcw.py

The good thing, these implementations looks similar. On the other hand it differs at least from the python's binascii implementation. This is also stated in the source comments. But it is also mentioned in the source comments that there is rellay no good documentation how to calculate the checksum:

  # Precise bit any byte ordering of the CRC calculation is
  # not clearly specified. This is empirical

As far as I can see the checksum is calculated from the beginning (including preamble) until the end command (including this 4 bytes).

I still try out any combinations of endian conversion (32bit), quad swap (without end command), and bit-order. Tried with the implementations from the source above and the binascii.crc32() implemention. 

Still not able to reproduce the checksum.

0 Kudos

2,046 Views
Pavel
NXP Employee
NXP Employee

Use polynomial 0x04c11db7.

The following code can be used for CRC calculation:

static void crc32_Polinom(byte data, uint polinomial32)

{

                byte i2;

                crc32 = crc32 ^ (uint)(data << 24);

                for (i2 = 0; i2 < 8; i2++)

                {

                               if ((crc32 & 0x80000000) != 0) crc32 = (crc32 << 1) ^ polinomial32;

                               else crc32 <<= 1;

                }

}

 

Result of CRC calculation from PBL file is 0.


Have a great day,
Pavel Chubakov

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,046 Views
addiyi
NXP Employee
NXP Employee

An easy why to generate the RCW is to use PBL tool, which it's a free tool for configure/generate/validate PBLs.

Adrian

0 Kudos

2,046 Views
Pavel
NXP Employee
NXP Employee

Look at the Section 28.8 of the LS1012a Reference Manual:

https://www.nxp.com/docs/en/reference-manual/LS1012ARM.pdf

 

Draw attention of QuadSPI_MCR[END_CFG] bit setting.

See attached snapshot. This snapshot shows command for changing 64bit BE to 64bit LE mode.

This changing shows that the last 64-bit word in the RCW should be swapped.

Look at RCW data after similar swapping.


Have a great day,
Pavel Chubakov

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,046 Views
hardsoft
Contributor II

Thanks for your help. In the Version of the RM you linked to, there is no section 28.8. I found the info you are most likely referring to in 26.9 on p 1502.
Ok I did not know that that is the specific command switching to LE. Very informative, it clarifies that the "internal" crc will probably be big endian and the last one little endian, but that does not really help me. I cannot recreate the individual bytes of the CRC32. I saw in byte_swap.tcl the effort made not to swap the last 8 bytes, so I was ... aware and tried to get the bytes in any order little endian, big endian, mixed endian or any permutation really. No luck yet. 

0 Kudos