-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: hwinfo: shell command "hwinfo devid" output ignores endianness #23444
Comments
IMO it is not an issue. The Zephyr device-id is a sequence of bytes. We make a 1:1 copy from the registers in the flash module. You should interpret the device ID as a byte sequence because other devices don't interpret them as u32_t. |
I agree with your assertion that the device ID should be interpreted as a byte sequence. However, that is not how the data is being read from the hardware. Rather, the bytes are read from the registers as integer values (u32_t) which inherently have endianness and then cast as a sequence of byte which potentially breaks the endianness of the integers. Here are a couple examples of this taken from the sam0 and nordic drivers: zephyr/drivers/hwinfo/hwinfo_sam0.c Lines 11 to 22 in 687d104
zephyr/drivers/hwinfo/hwinfo_nrf.c Lines 12 to 21 in 687d104
The data structure receiving contents of the hardware registers is declared as a struct with u32_t members. Each one of those members has endianness. When you simply copy them using memcpy, endianness is not accounted for. In this case, ARM is little endian so the words are byte reversed. |
Using memcpy on the struct just makes a 1:1 copy. It does not change the endianness. The registers are interpreted as they were in a contiguous memory region somewhere in the registers. |
Correct, memcpy makes a copy of the struct. However, the data types that comprise the struct have endianness. |
@alexanderwachter I think @sslupsky is right, the fields should be in the CPU endianness, will you send a patch? or @sslupsky would you consider sending one? |
@carlescufi I think that if the vendor has a preferred expression of the hardware identifier as formed from the raw data that should be followed. IOW if the hardware identifier for Nordic is low-word then high-word little-endian, maybe there's some swapping to be done to get an octet sequence that matches the intended one, e.g. for Bluetooth addresses. I agree with @alexanderwachter that a memcpy of the raw bytes from the starting address is a legitimate interpretation of the hardware id, unless the vendor specifies that the value has a canonical representation. I don't know how Atmel expects people to interpret the hardware identifier values. But for the purposes of this API the interpretation should be a sequence of octets. It should not be reversed when creating a representation, as noted in #24103. |
@pabigot My point is what you described is not what is happening here. The driver does not use memcpy to read the raw bytes from the starting address. It first reads the data as u32_t and then uses memcpy to copy the data. This approach ensures there is endianness in the data. |
If it reads and writes Nonetheless, I think we agree that if Nordic wants |
Agreed, consumers of the hwinfo data should not be expected to do transformations on the bytes. That is at the core of what I am trying to get to consensus with on this issue. The consensus on this determines if the root cause of the problem is:
Your suggestion, and I believe @alexanderwachter said this too, is that the data structure should be a "sequence of bytes". I agree. So, that confirmation then suggests that the driver(s) should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then hwinfo_shell outputs the data as a sequence of bytes, which of course then has endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This issue likely extends to all the other drivers in the tree where the MCU is little endian. |
I think the change can be done efficiently using sys/byteorder.h as follows:
nordic:
I have tested the sam0 driver and it works fine. Can you please test the nordic patch and let me know if it provides what you want? Do the words need to be swapped as well in the nordic driver? |
I believe (without testing) that Nordic must be:
as the stored value is a little-endian 64-bit integer. That's why reversing the entire 8-byte sequence is being done for USB. |
@carlescufi submitted a PR for this: |
I tested the sam0 but cannot test the nordic change. I conferred with @pabigot about the change to the nordic driver and it looks ok. It was a slightly different change than the sam0 driver because of the word size. |
HWINFO drivers should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then memcpy the data to a buffer. This ensures the data has the endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This commit fixes the endianness so the data can be interpreted as a "left to right sequence of bytes". This commit updates the API doc to provide clarification of the data structure. Add to 2.3 release notes. Fixes zephyrproject-rtos#23444, zephyrproject-rtos#24103 Signed-off-by: Steven Slupsky <[email protected]>
HWINFO drivers should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then memcpy the data to a buffer. This ensures the data has the endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This commit fixes the endianness so the data can be interpreted as a "left to right sequence of bytes". This commit updates the API doc to provide clarification of the data structure. Add to 2.3 release notes. Fixes #23444, #24103 Signed-off-by: Steven Slupsky <[email protected]>
HWINFO drivers should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then memcpy the data to a buffer. This ensures the data has the endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This commit fixes the endianness so the data can be interpreted as a "left to right sequence of bytes". This commit updates the API doc to provide clarification of the data structure. Add to 2.3 release notes. Fixes zephyrproject-rtos#23444, zephyrproject-rtos#24103 Signed-off-by: Steven Slupsky <[email protected]>
HWINFO drivers should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then memcpy the data to a buffer. This ensures the data has the endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This commit fixes the endianness so the data can be interpreted as a "left to right sequence of bytes". This commit updates the API doc to provide clarification of the data structure. Add to 2.3 release notes. Fixes zephyrproject-rtos#23444, zephyrproject-rtos#24103 Signed-off-by: Steven Slupsky <[email protected]>
HWINFO drivers should be responsible for ensuring that the data structure is a sequence of bytes. That is not what the current sam0 and nordic drivers do. The drivers read the data as u32_t and then memcpy the data to a buffer. This ensures the data has the endianness of the underlying MCU, which in this case is Cortex M0 which is little endian. This commit fixes the endianness so the data can be interpreted as a "left to right sequence of bytes". This commit updates the API doc to provide clarification of the data structure. Add to 2.3 release notes. Fixes zephyrproject-rtos#23444, zephyrproject-rtos#24103 Signed-off-by: Steven Slupsky <[email protected]>
Describe the bug
When using the "hwinfo devid" shell command to display the device id, the command outputs the device id but the bytes of each word comprising the ID appear to print in the wrong order. I believe this is because the print statements do not appear to consider endianness.
To Reproduce
Steps to reproduce the behavior:
Compile app with CONFIG_HWINFO and CONFIG_HWINFO_SHELL
Step A: From main on sam0 arch, print the device id:
Step B: Invoke the shell command from the console:
hwinfo devid
Step C: Compare results.
Expected behavior
Step A on sam0 produces:
Device ID: 0x2f89032e5050323339202020ff0a0c0f
Step B on sam0 produces:
Length: 16
ID: 0x2e03892f33325050202020390f0c0aff
Comparison shows the 32 bit words that comprise the ID are in the correct order. However, the 4 bytes that comprise each word are reversed.
Impact
Minor annoyance but could be a major issue for anyone using the ID as a UID for something like a firmware update, networking, etc.
Screenshots or console output
The code that outputs the id is:
zephyr/drivers/hwinfo/hwinfo_shell.c
Lines 32 to 34 in 687d104
The SAMD21 data sheet describes the ID as follows:
Each device has a unique 128-bit serial number which is a concatenation of four 32-bit words
From the datasheet description, does this suggest the ID should be output using Big Endian format?
The text was updated successfully, but these errors were encountered: