Skip to content
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

Firmware update #460

Open
floe opened this issue Nov 9, 2015 · 39 comments
Open

Firmware update #460

floe opened this issue Nov 9, 2015 · 39 comments

Comments

@floe
Copy link
Contributor

floe commented Nov 9, 2015

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/

/cc @xlz @marcan @qdot @christiankerl @larshg @sh0

@xlz
Copy link
Member

xlz commented Nov 9, 2015

Are there some textual descrptions for kinect1.pcap kinect2.pcap kinect3.pcap? Which one should I look at?

@floe
Copy link
Contributor Author

floe commented Nov 9, 2015

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.

@xlz
Copy link
Member

xlz commented Nov 9, 2015

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.

@floe
Copy link
Contributor Author

floe commented Nov 10, 2015

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?

@sh0
Copy link

sh0 commented Nov 10, 2015

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.

@xlz
Copy link
Member

xlz commented Nov 10, 2015

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

@sh0
Copy link

sh0 commented Nov 10, 2015

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

@xlz
Copy link
Member

xlz commented Nov 10, 2015

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.

@xlz
Copy link
Member

xlz commented Nov 10, 2015

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.

@sh0
Copy link

sh0 commented Nov 10, 2015

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.

@xlz
Copy link
Member

xlz commented Nov 10, 2015

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 like unk0c means bool no_upload, being 1 for id 0,4 and 0 for 1,2,3,5,6). These two are "critical" sections.
  • What is the possible purpose of each blob?

@floe
Copy link
Contributor Author

floe commented Nov 10, 2015

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?

@xlz
Copy link
Member

xlz commented Nov 11, 2015

@sh0 I think that is not two blobs. The second "Sign" is the code that checks the signature.

@sh0
Copy link

sh0 commented Nov 11, 2015

@xlz All makes sense now, the second 'Sign' tag threw me off on a wild goose chase.

@floe
Copy link
Contributor Author

floe commented Nov 11, 2015

Somewhat related, and maybe helpful for whipping up a couple of scripts: http://pythonarsenal.com/

@xlz
Copy link
Member

xlz commented Nov 12, 2015

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?

@xlz
Copy link
Member

xlz commented Nov 13, 2015

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       

@floe
Copy link
Contributor Author

floe commented Nov 16, 2015

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.

@xlz xlz modified the milestone: 0.2 Jan 21, 2016
@xlz xlz modified the milestones: 0.2, 0.3 Feb 26, 2016
@nioyco
Copy link

nioyco commented Aug 21, 2016

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

@mpatalberta
Copy link

does anyone know what is the latest firmware version and what are the features or improvements

@xlz
Copy link
Member

xlz commented Mar 3, 2017

@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.

@miguelgines
Copy link

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?

@xlz
Copy link
Member

xlz commented Mar 5, 2017

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.

@miguelgines
Copy link

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?

@floe
Copy link
Contributor Author

floe commented Mar 6, 2017

Protonect is the software which this issue tracker is about. I suggest you check a Microsoft support site.

@xlz xlz removed this from the 0.3 milestone Apr 4, 2017
@shevart75
Copy link

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!

@mpatalberta
Copy link

mpatalberta commented Apr 21, 2020 via email

@shevart75
Copy link

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?

@CarlosGS
Copy link

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.

@mpatalberta
Copy link

mpatalberta commented Apr 27, 2020 via email

@CarlosGS
Copy link

Thank you Patrick! I will set up a windows VM and do it for all the Kinects just in case. Cheers!

@shevart75
Copy link

how to check the version without firmware update?

@shevart75
Copy link

shevart75 commented May 17, 2020

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?

@shevart75
Copy link

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.

@shevart75
Copy link

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.

@parkerlreed
Copy link

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?

@My1
Copy link

My1 commented May 6, 2024

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

@parkerlreed
Copy link

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

@My1
Copy link

My1 commented May 9, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants