Firmware update
floe opened this issue · 39 comments
Hi everyone, one of the features still missing from libfreenect2 is the firmware update. I had the opportunity to get an USB3 capture of an outdated Kinect v2 getting connected to an official SDK running on Windows 10 in a VM; I didn't have time so far to analyze it. If anybody is interested in digging into the raw PCAP files (which, in theory, should of course also include the firmware itself), I'm making them available here: http://floe.butterbrot.org/external/firmware_pcap/
Are there some textual descrptions for kinect1.pcap kinect2.pcap kinect3.pcap? Which one should I look at?
Sorry - the first kinect1.pcap is probably not very useful (lots of connect & disconnect events), kinect2 and kinect3 should in theory contain one full update process + some image streaming afterwards.
I'm able to extract 5 firmware blobs. They seem to be signed. I think they are copyrighted code.
-rw-r--r-- 1 xlz xlz 61440 Nov 9 12:23 1.bin
-rw-r--r-- 1 xlz xlz 61440 Nov 9 12:23 2.bin
-rw-r--r-- 1 xlz xlz 61440 Nov 9 12:23 3.bin
-rw-r--r-- 1 xlz xlz 4300 Nov 9 12:22 5.bin
-rw-r--r-- 1 xlz xlz 4300 Nov 9 12:23 6.bin
I transcribed the pcaps to readable commands https://gist.github.com/xlz/1d737766bb5a97f77475. (Values of firmware blobs, camera parameters, p0 tables are removed.)
Basically it uses 0x04 command to upload a blob to certain firmware "segment", and once for each of 1,2,3,5,6 segments. Then uses 0x05 command to check status until certain success condition. It seems there will be port reset after each upload. I'm not sure who initiated this. Also Microsoft SDK checks firmware versions again and again, not sure of the meaning.
There are two major issues about the firmware update feature:
- There has to be a way to retrieve the firmware blobs from Microsoft sources. Firmware is copyrighted so it can't be included in libfreenect2. Where do they come from in this case, are the firmware blobs generated by KinectService.exe or downloaded from Microsoft website?
- Concern of bricking the hardware by firmware flashing bugs.
Impressive work, as always. Is there a way to tell what architecture the firmware is for, e.g. for disassembly?
I would assume that the firmware is part of KinectService; however, I didn't check for network traffic simultaneously. I'd also refrain from actually adding any firmware update capability to libfreenect2; at most, I would suggest to add a tool to manually poke at the Kinect using command 0x04. Did you see anything that might be a firmware download command?
The firmware blobs are baked into KinectService.exe
(version v2.0_1409
) using custom executable resource (type = RCDATA
, id = 101
). This resource file could be extracted using standard tools or be copied straight from file (offset = 0x00389b80 = 3709824
, size = 0x000ff9d0 = 1046992
).
This resource blob starts with 'INAM' and hence I call it INAM file. The following structure describes the header:
struct s_inam {
0x00: char[4] magic; // = "INAM"
0x04: uint32_t version; // = 1
0x08: uint32_t entries_offset; // = 0x20 = 32 // from file start
0x0c: uint32_t entries_count; // = 7
0x10: uint32_t unk10; // = 0x0666fa92 = 107412114
0x14: uint32_t unk14[3]; = { 0, 0, 0 }
};
Firmware blob entry table follows the header:
struct s_entry {
0x00: uint32_t id;
0x04: uint32_t offset; // from file start
0x08: uint32_t size;
0x0c: uint32_t unk0c; // = 0 or 1
0x10: uint16_t version[8]; // = { 0000 0400 470f 0000 0000 0000 0000 0000 }
0x20: uint8_t unk20[0x10]; // all zeroes
}; // size = 0x30 = 48
Each firmware blob has following layout:
struct s_firmware {
// signature [0x0117]
0x0000: char[4] signature_magic; // = "Sign"
0x0004: uint32_t signature_size; // = 0x010c = 268
0x0008: uint32_t signature_version; // = 0
0x000c: uint8_t signature_data[0x010c];
// header [0x0034]
0x0118: uint16_t header_version[8]; // = { 0000 0400 470f 0000 0000 0000 0000 0000 }
0x0128: uint32_t header_address_a;
0x012c: uint32_t header_address_b;
0x0130: uint32_t header_size;
0x0134: uint32_t header_crc32;
0x0138: uint32_t header_0138; // = 1
0x013c: uint32_t header_013c; // = 2
0x0140: uint32_t header_0140; // = 0
0x0144: uint32_t header_0144; // = 0
0x0148: uint32_t header_0148; // = 0
// content
0x014c: uint8_t content[header_size];
}
There are 7 firmware blobs with following details:
fw00: address_a = 0x00000000, address_b = 0xffff0040, size = 0x00003b30 = 15152
fw01: address_a = 0x20400040, address_b = 0x204006a8, size = 0x0001bdb8 = 114104
fw02: address_a = 0x20400040, address_b = 0x20400680, size = 0x0001bdb8 = 114104
fw03: address_a = 0x20010040, address_b = 0x2001239c, size = 0x000c13fc = 791548
fw04: address_a = 0x00000000, address_b = 0x00000000, size = 0x00000100 = 256
fw05: address_a = 0x00000000, address_b = 0x00000000, size = 0x00000f80 = 3968
fw06: address_a = 0x00000000, address_b = 0x00000000, size = 0x00000f80 = 3968
Files fw00
to fw03
are ARM code. For some reason fw01
and fw02
have exactly same content so there are only 3 distinct files with executable code. The address_a
and address_b
fields are related to ROM loading/start addresses. fw03
contains some tables at the end of the file. Files fw04
to fw06
contain some unknown data tables.
md5sums of the 5 blobs.
5e9b38f2a22920f88f8ce05c47359c4b 1.bin
ff4b2bf423814b4c17e4b503261c482a 2.bin
4b9a03ad0b5f70effa1a784a8925814f 3.bin
0cdad3462a01c7bccd4898a743565453 5.bin
fa465151f5ddca455ca2306a6650117b 6.bin
@sh0 See if you can map the uploaded segment number with fw0?. https://gist.github.com/xlz/ba98525d8f7b8472f2b9
I uploaded all relevant files here. *.bin
files are the signed blobs (start with Sign
tag) and *.arm
files contain only the firmware content (with headers stripped).
Also here are the md5 sums for convenience:
444d68c9292cc91fe3ea12220e350e48 firmware-00.arm
07f2d865e48463c4aea3396580969112 firmware-01.arm
07f2d865e48463c4aea3396580969112 firmware-02.arm
6b29cb23136eea94556821e47bbbb14c firmware-03.arm
ceb844f25840855a8694e4715b38b0ea firmware-04.arm
04bcec8d28dcd04c32631d4ecadea356 firmware-05.arm
fb1bdcf74a2c3a5972fb7cf74bc40830 firmware-06.arm
ef94ebec25cd0b367085fb0d2c826222 firmware-00.bin
4b8f53411b3980d171780adaee28de12 firmware-01.bin
1050a58366240469224ab71c303a97b8 firmware-02.bin
33f741bc072d7fc28c0a433a4f956b32 firmware-03.bin
bdc789ba57a7ceefab833124197f40dd firmware-04.bin
0cdad3462a01c7bccd4898a743565453 firmware-05.bin
fa465151f5ddca455ca2306a6650117b firmware-06.bin
are baked into KinectService.exe
Then the update mechanism should be Windows driver update. From my experience Windows will automatically install Kinect Runtime without asking for any EULA or licenses. The runtime is also here http://www.microsoft.com/en-us/download/details.aspx?id=44559. It looks like it has no EULA or licenses, so the user can just download and update that and extract firmware blobs without installing it.
Did you see anything that might be a firmware download command?
I didn't see any. The transcribed commands are all the bulk transfers. There were no other bulk transfers.
So firmware-0{1,2,3}.bin and {1,2,3}.bin have the same content for the first 0xf000 bytes. And firmware-0{5,6}.bin {5,6}.bin are the same.
I just figured out why fw01
and fw02
look similar - both actually contain two signed blobs. First blob starts at 0x0000
and the second one at 0xf0ec
.
Also fw03
has blobs at 0x000000
and 0x021fb4
.
There are a few more questions:
- What is the correct length for uploading? The uploaded length is shorter than the available length.
Why are firmware 0 and 4 not uploaded? (Looks likeThese two are "critical" sections.unk0c
meansbool no_upload
, being 1 for id 0,4 and 0 for 1,2,3,5,6).What is the possible purpose of each blob?
Just speculation, but is it possible that blobs 0 and 4 are basically just backups? I.e. firmware is usually present in two copies, and one copy is preserved in case the update or signature check fails?
@sh0 I think that is not two blobs. The second "Sign" is the code that checks the signature.
Somewhat related, and maybe helpful for whipping up a couple of scripts: http://pythonarsenal.com/
KinectFirmwareUpdate.exe is a standalone tool in Kinect SDK <= v2.0_1406. It has this string:
-critical Use with extreme caution and use only if explicitly
directed! This option will update the sensor's
boot critical files.
This makes sense, because blob 0 really starts with "d3 f0 21 e3", a bootloader pattern. So unk0c
means critical. This probably means failed firmware flashing would not brick the hardware if the critical sections are not touched.
Still, from what I see in KinectFirmwareUpdate.exe, the entire blobs are meant to be uploaded. Cutoff at 0xf000 bytes is really weird. Is it something with incomplete capturing, or KinectService.exe (which is a lot harder to look at than) does something different than KinectFirmwareUpdate.exe?
Pseudocode for firmware upload ripped from KinectService.exe
(Only consider non-critical blob in any situation.)
upload firmware(inam.bin)
parse blob addresses sizes in inam.bin
loop 16 times:
read device firmware versions
if no blob version is newer
break
upload firmware once
shutdown/disconnect device
connect/initialize device
upload firmware once(blobs)
read firmware versions
for each blob in blobs (order would be 5,6,1,2,3)
if old veresion is 0.0.0.0 (previously failed upload?!)
upload firmware blob
return
for each blob in blobs
if old version < blob version
upload firmware blob
return
upload firmware blob(blob_id, blob_mem, blob_size)
send command cmd=0x04 param=blob_id data=blob_mem,blob_size
failures = 0
while 1:
sleep 100ms
send command cmd=0x05, return status: struct {int state; int progress; int completion_status}
if failed:
if failures > 5
break
failures += 1
continue
if status.state == 0 (IDLE):
break
if status.state == 1 (COMPLETION):
break
if status.state > 5 (MAX):
break
It's entirely possible that the capture is cut short, for whatever reason. I may have missed some option for dumpcap
.
I'll also check if all firmware versions are now again the same on the updated cameras; IMHO this would indicate that blobs 0 and 4 are indeed backups that are then updated internally once the new firmware has booted successfully.
Could someone share me the KinectFirmwareUpdate.exe standalone?
(Impossible to find the "kinect v2 developper preview" which include the file)
It seems newer version don't include it
does anyone know what is the latest firmware version and what are the features or improvements
@mpatalberta Personally I think you should just use Windows to update the firmware. There is too much risk in doing it in a reverse engineered way to outweigh its worth.
You can find the latest firmware version by downloading the official driver and unpacking it.
Hello I work for a tech company and we are using the kinect sensors for some R&D work. Any information will be helpful, thank you in advance;
1)How can I find out what firmware our current kinect v2 sensors have?
2)What is the latest firmware version for the kinect v2 sensors out now?
3)How can I update a kinect v2 sensor that has an older firmware version with the latest version using a labtop with windows 7 professional?
1)How can I find out what firmware our current kinect v2 sensors have?
Protonect prints firmware version.
2)What is the latest firmware version for the kinect v2 sensors out now?
Check Microsoft.
3)How can I update a kinect v2 sensor that has an older firmware version with the latest version using a labtop with windows 7 professional?
You can't. You must use Windows 8 or later.
Thank you. What is "protonect" and using a windows 8 system how can I update the firmware to a xbox one kinect with windows adapter? I couldnt find anyting on microsoft website for the latest version of firmware. Maybe I can call them?
Protonect is the software which this issue tracker is about. I suggest you check a Microsoft support site.
Hello,
I have received an old 1520 model. Xbox one shows Kinect version: 4.0.3917.0:7
Is it the firmware version?
I also have a Kinect 1595 from China which I have connected to Win10 and updated using SDK. Xbox one shows for it now: 4.0.3917.0:257
Would it be helpful for you to if I do a capture of USB and TCP/whatever to get more insigts into the firmware update process?
Is there a way to read out firmware from Kinect prior to or at best without an update?
Regards!
yes, but was the result satisfactory?
was the capture complete that time?
do you need another test to confirm?
Is the issue with firmware update solved?
How to read out the firmware out of kinect?
Do we have answers to these questions?
Could someone summarize how to check the version, what are the missing features, and how to update the kinect? I honestly have no idea on what are the repercussions of using an older version. Thank you.
Thank you Patrick! I will set up a windows VM and do it for all the Kinects just in case. Cheers!
how to check the version without firmware update?
The new azure kinect sdk contains some information on the process of updating the firmware
https://docs.microsoft.com/de-de/azure/kinect-dk/azure-kinect-firmware-tool
Maybe it can help to understand the v2 process?
Also I have read that it is possible to hardreset the firmware to a factory setting by pressing the button hidden behind the mounting screw on the bottom of the camera.
It means that at least wit azure kinect it is always possible to unbrick it if something went wrong.
Also, AzureKinectFirmwareTool.exe has a nice feature -r to reset to a predefined state.
can someone provide a link to where to get the KinectFirmwareUpdate.exe?
Can it have the same option?
We know now, that inside of kinect v2 there is Macronix MX25L25635F 256 MB serial flash (256Mbit = 32Mbyte)
One could unsolder one from the main board and read it out it via SPI.
Then one would probably be able to find the corresponding chunks of code in those .bin files.
The main SoC chip is Microsoft X871141-001 which replaces the Prime Sense chip used in the first Kinect. it's from STMicroelectronics.
It does Time of Flight and probably also the USB and booting etc.
So the firmware update is persistent and doesn't require the use of the Windows SDK every time? Is there a way to check what version we are on not within WIndows?
So the firmware update is persistent and doesn't require the use of the Windows SDK every time? Is there a way to check what version we are on not within WIndows?
literally just use the Protonect program bundled with this project:
my1@my1-qbp:~/codestuff/libfreenect2/build$ ./bin/Protonect
Version: 0.2.0
Environment variables: LOGFILE=<protonect.log>
Usage: ./bin/Protonect [-gpu=<id>] [gl | cl | clkde | cuda | cudakde | cpu] [<device serial>]
[-noviewer] [-norgb | -nodepth] [-help] [-version]
[-frames <number of frames to process>]
To pause and unpause: pkill -USR1 Protonect
[Info] [Freenect2Impl] enumerating devices...
[Info] [Freenect2Impl] 15 usb devices connected
[Info] [Freenect2Impl] found valid Kinect v2 @6:11 with serial NOPE
[Info] [Freenect2Impl] found 1 devices
[Info] [Freenect2DeviceImpl] opening...
[Info] [Freenect2DeviceImpl] transfer pool sizes rgb: 20*16384 ir: 60*8*33792
[Info] [Freenect2DeviceImpl] opened
[Info] [Freenect2DeviceImpl] starting...
[Debug] [Freenect2DeviceImpl] status 0x090000: 9757
[Debug] [Freenect2DeviceImpl] status 0x090000: 9731
[Info] [Freenect2DeviceImpl] submitting rgb transfers...
[Info] [Freenect2DeviceImpl] submitting depth transfers...
[Info] [Freenect2DeviceImpl] started
device serial: NOPE
device firmware: 4.0.3917.0 <<<<<------------------------ THIS
[Debug] [DepthPacketStreamParser] not all subsequences received 0
[Info] [OpenGLDepthPacketProcessor] avg. time: 4.77099ms -> ~209.6Hz
[Info] [Freenect2DeviceImpl] stopping...
[Info] [Freenect2DeviceImpl] canceling rgb transfers...
[Info] [Freenect2DeviceImpl] canceling depth transfers...
[Info] [Freenect2DeviceImpl] stopped
[Info] [Freenect2DeviceImpl] closing...
[Info] [Freenect2DeviceImpl] releasing usb interfaces...
[Info] [Freenect2DeviceImpl] deallocating usb transfer pools...
[Info] [Freenect2DeviceImpl] closing usb device...
[Info] [Freenect2DeviceImpl] closed
[Info] [Freenect2DeviceImpl] closing...
[Info] [Freenect2DeviceImpl] already closed, doing nothing
So the firmware update is persistent and doesn't require the use of the Windows SDK every time? Is there a way to check what version we are on not within WIndows?
literally just use the Protonect program bundled with this project:
my1@my1-qbp:~/codestuff/libfreenect2/build$ ./bin/Protonect Version: 0.2.0 Environment variables: LOGFILE=<protonect.log> Usage: ./bin/Protonect [-gpu=<id>] [gl | cl | clkde | cuda | cudakde | cpu] [<device serial>] [-noviewer] [-norgb | -nodepth] [-help] [-version] [-frames <number of frames to process>] To pause and unpause: pkill -USR1 Protonect [Info] [Freenect2Impl] enumerating devices... [Info] [Freenect2Impl] 15 usb devices connected [Info] [Freenect2Impl] found valid Kinect v2 @6:11 with serial NOPE [Info] [Freenect2Impl] found 1 devices [Info] [Freenect2DeviceImpl] opening... [Info] [Freenect2DeviceImpl] transfer pool sizes rgb: 20*16384 ir: 60*8*33792 [Info] [Freenect2DeviceImpl] opened [Info] [Freenect2DeviceImpl] starting... [Debug] [Freenect2DeviceImpl] status 0x090000: 9757 [Debug] [Freenect2DeviceImpl] status 0x090000: 9731 [Info] [Freenect2DeviceImpl] submitting rgb transfers... [Info] [Freenect2DeviceImpl] submitting depth transfers... [Info] [Freenect2DeviceImpl] started device serial: NOPE device firmware: 4.0.3917.0 <<<<<------------------------ THIS [Debug] [DepthPacketStreamParser] not all subsequences received 0 [Info] [OpenGLDepthPacketProcessor] avg. time: 4.77099ms -> ~209.6Hz [Info] [Freenect2DeviceImpl] stopping... [Info] [Freenect2DeviceImpl] canceling rgb transfers... [Info] [Freenect2DeviceImpl] canceling depth transfers... [Info] [Freenect2DeviceImpl] stopped [Info] [Freenect2DeviceImpl] closing... [Info] [Freenect2DeviceImpl] releasing usb interfaces... [Info] [Freenect2DeviceImpl] deallocating usb transfer pools... [Info] [Freenect2DeviceImpl] closing usb device... [Info] [Freenect2DeviceImpl] closed [Info] [Freenect2DeviceImpl] closing... [Info] [Freenect2DeviceImpl] already closed, doing nothing
WHAT YEAR IS IT??? Hah :D
So yeah I'm an update behind. Still no way to update this from Linux?
device firmware: 4.0.3916.0
well obviously there is no official way and the consensus seems to have been that it isn't worth the risk hacking a firmware update in.
also it's 2024.