Skip to content

Conversation

apatard
Copy link
Contributor

@apatard apatard commented Feb 18, 2025

Add support for rockchip maskrom mode. It can send files generated with boot_merger and for SoC with older
IDB format, it can generated the blob at run time. For SoCs with IDB v2, some extra work is needed atm.

note: rockusb protocol is not supported, as booting with u-boot will allow using things like dfu / ums / fastboot

@apatard apatard marked this pull request as ready for review February 20, 2025 14:05
@rgantois
Copy link
Collaborator

That is a very interesting contribution :) thanks a lot!

I'll have to take some time to review it thoroughly, but at first glance the overall code organization looks good to me.

I'll see if I can get it to work on RK3308 since I have a rockpis lying around.

@apatard
Copy link
Contributor Author

apatard commented Feb 21, 2025

fyi, this u-boot series may be interesting: https://patchwork.ozlabs.org/project/uboot/list/?series=445397 as, maybe, we can avoid having to download u-boot proper with DFU. I've yet to test it and check it's working as I understand.

@apatard
Copy link
Contributor Author

apatard commented Feb 21, 2025

fwiw, tested this series, and managed to boot u-boot proper without DFU on rk3399 and rk3588. On rk3588, I've had to disable rc4 encryption so I've updated the PR accordingly

@rgantois
Copy link
Collaborator

Hi, I'm starting to review this and there's one thing I've noticed so far: your series is missing documentation on the images which need to be passed to snagrecover. Every SoC family needs a section in docs/fw_binaries.md which describes which firmware binaries are expected by snagrecover and what these binaries contain.

The README will also have to be updated to specify that Rockchip SoCs are supported.

I'll come back with more details once I've had time to test and review this in depth.

Copy link
Collaborator

@rgantois rgantois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good! Apart for the comments in this review, there's also the point about docs/fw_binaries.md that I mentionned before.

I've confirmed that the first stage part works with a RockPiS board but unfortunately, there isn't SPL DFU support for the RK3308 SoC in U-Boot, so I couldn't test the second stage.

Thanks!

@apatard
Copy link
Contributor Author

apatard commented Mar 21, 2025

I've confirmed that the first stage part works with a RockPiS board but unfortunately, there isn't SPL DFU support for the RK3308 SoC in U-Boot, so I couldn't test the second stage.

For SPL DFU, I've tested it on rk3399 with patches I've sent on the u-boot mailing list. The same day someone from Radxa sent patches for a bunch of rockchip SoCs to enable it but I've not tested the serie. You may want to test that. Nevertheless, these days, I've been using the ramboot-v1 patches mentioned here and they're working at least on rk3399 and rk3588*. It should work on rk3308 too.

@oli-ben oli-ben linked an issue Mar 24, 2025 that may be closed by this pull request
Copy link

@oli-ben oli-ben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Arnaud, thanks very much for your work!

I have tested this on an RK3399 using DFU and successfully booted.

I have not tried the UBoot changes that allow using it without DFU.
I do think more documentation would be helpful for users to be able to use this feature.

logger.info(f"Sleeping {delay}ms")
time.sleep(delay / 1000)
else:
cli_error("Missing xpl or code471/code472 binary configuration")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Missing xPL or code471 ('*_ddr_*.bin')/code472 (*_usbplug_*.bin) binary configuration" would be even more helpful, as this would indicate what binaries "code471" and "code472" are supposed to be, which is not necessarily obvious if you're trying to use the tools without being super familiar with Rockchip internals.

path: rk3399_uboot.bin
u-boot-fit:
# proper u-boot
path: u-boot.itb
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I tested this on RK3399, trying to load u-boot.itb directly failed for me.

Loading simple-bin.fit.itb, however, worked perfectly.
This required quite a few patches to U-Boot (including some specific to my board, which has rather poor support upstream).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird. I'll test later if the simple-bin.fit.itb is working for me too. In this case, I'll update things to use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested on my rock5c. Don't know why but simple-bin.fit.itb didn't work. I'll have to do more testing later :(

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current implementation of support for the Rockchip SoCs, RAMboot and
SPL DFU are supported.

I'm having trouble understanding what you meant here. Was it something like:

Snagboot currently supports two methods for Rockchip SoC recovery: RAM boot, and SPL DFU

Otherwise, regarding this part:

As there's no implementation for Rockchip USB protocol support, it is
possible to push the DDR init files and SPL files from Rockchip but the next
step will fail.

IIUC, prebuilt files don't work because SPL won't expose a USB gadget. If that's correct, then I'd reword this:

Using a precompiled SPL from Rockchip will not work, as it is usually not configured to communicate over USB.

Finally, in this part:

Mainline u-boot does not support boot from RAM and boot from SPL DFU,
it has to be patched.

s/boot/booting

Copy link
Collaborator

@rgantois rgantois left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the improvements, there are still a few changes needed, mostly in the doc section. The rest looks good to me.


## For Rockchip devices

While it is possible to use the DDR init files and SPL files from Rockchip,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it really possible to use snagrecover with the prebuilt SPL images from Rockchip? I don't think that's true in the general case, since they don't have DFU support.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to use rockchip files but as it was noted, it won't be helpful, as there's no rockusb support in snagflash. I've rewritten this part. Is it better now ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose you meant "snagrecover" and not "snagflash". Nevertheless, this is a bit confusing to me. Could we use the prebuilt binaries from Rockchip if Snagrecover had a RockUSB implementation? IIRC the issue was that the prebuilt SPL didn't expose a USB gadget at all, but maybe I'm misremembering this.

it is easier to use the files generated by u-boot as support for the
Rokchip USB protocol is not implemented.
Nevertheless, this means that to boot u-boot proper, u-boot has to be
patched to get support for:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be clear here: using the prebuilt Rockchip SPL images doesn't work with Snagrecover. People have to patch U-Boot and build the images themselves.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. I've rewritten this part. Please, check if it's clearer/better now.

- ``mkimage-in-simple-bin.mkimage-u-boot-tpl`` or ``mkimage-in-simple-bin.mkimage-rockchip-tpl``
- ``mkimage-in-simple-bin.mkimage-u-boot-spl``
- ``u-boot.itb``

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you're missing a "configuration:" after the "u-boot-fit:" entry.

Copy link
Contributor

@Foutete Foutete left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Arnaud,
I tested your PR with a rk3308-based board and with u-boot 2025.01 with the patch from https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot/-/merge_requests/5/commits.

Here are a few minor suggestions.

Regards,
François

crcbytes = crc.final()
chunk.append(crcbytes >> 8)
chunk.append(crcbytes & 0xff)
written = self.__write_chunk(addr, chunk)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got an issue when using the 'Boot from RAM' method:
snagrecover -s rk3308 -f rockchip-ramboot.yaml failed with the following error :

[INFO] Starting recovery of rk3308 board
[INFO] Installing firmware code471
[INFO] Downloading code471...
[INFO] Done installing firmware code471
[INFO] Sleeping 1ms
[INFO] Installing firmware code472
[INFO] Downloading code472...
[INFO] CLI error: Failed to run code472 firmware: [Errno 110] Operation timed out

even though the board correctly booted u-boot proper.

It seems like, when sending the CRC in write_blob, the USB request times out.

A possible solution would be to set the timeout to a bigger value for this USB request (5 seconds were enough in my case).
Wireshark reports the following answers (target to host) for the CRC answer:

timeout 1000ms timeout 5000ms
URB status: No such file or directory (-ENOENT) (-2) URB status: Success (0)
[Time from request: 1.000119000 seconds] [Time from request: 4.623689000 seconds]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, that's sad. I've added a timeout of 5 seconds. Can you please test to see if it's fine now ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Arnaud, thanks for your changes.
I have tested your fix and it works fine for me.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got an issue when using the 'Boot from RAM' method: snagrecover -s rk3308 -f rockchip-ramboot.yaml failed with the following error :

[INFO] Starting recovery of rk3308 board
[INFO] Installing firmware code471
[INFO] Downloading code471...
[INFO] Done installing firmware code471
[INFO] Sleeping 1ms
[INFO] Installing firmware code472
[INFO] Downloading code472...
[INFO] CLI error: Failed to run code472 firmware: [Errno 110] Operation timed out

even though the board correctly booted u-boot proper.

It seems like, when sending the CRC in write_blob, the USB request times out.

A possible solution would be to set the timeout to a bigger value for this USB request (5 seconds were enough in my case). Wireshark reports the following answers (target to host) for the CRC answer:

timeout 1000ms timeout 5000ms
URB status: No such file or directory (-ENOENT) (-2) URB status: Success (0)
[Time from request: 1.000119000 seconds] [Time from request: 4.623689000 seconds]

Some SOCs (sorry I can't remember) require a longer timeout... I'm using 30s for it ;)

https://github.com/RadxaNaoki/rkusbboot/blob/main/rkusbboot.c#L75

```
CONFIG_SPL_DM_USB_GADGET=y
CONFIG_SPL_USB_GADGET=y
CONFIG_SPL_DFU=y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I encountered an issue while using this configuration. After
recompilation of U-Boot, only my SPL was being updated, i needed to power cycle the board to
be able to update U-Boot Proper.

I found out that the board's DDR was not properly erased after a reset,
thus when using snagrecover with DFU to update both u-boot, SPL was correctly updated but would boot an old u-boot proper instead of retrieving it through DFU, since DFU comes after RAM in SPL boot order.

A solution to this would be to disable U-Boot's configuration option CONFIG_SPL_RAM_DEVICE=n Support booting from preloaded image in RAM.

Could you please add this option to the list along with the explanation that I gave?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right. On reset/reboot, the RAM is not reset so it'll find the ramboot binary and use it instead of DFU. I've added some notes in the doc about that.

apatard added 4 commits June 2, 2025 18:51
Add support for uploading blods to the maskrom memory using Rockchip
maskrom protocol.

Signed-off-by: Arnaud Patard <[email protected]>
``offset`` is too generic, so rename it to ``class_offset``.

Signed-off-by: Arnaud Patard <[email protected]>
…in files

Add support for reading and sending rockchip binary files, made with
boot_merger.

Signed-off-by: Arnaud Patard <[email protected]>
Add support for booting a rockchip bin file, made with boot_merger.
It can be:
- a file containing the rockchip miniloader, but in this case,
  it's not useful, as rockusb is not implemented
- a file containing uboot tpl and spl. In this case, if u-boot
  is configured for SPL DFU, the snagrecover configuration file
  may specify an u-boot FIT image to load into the first DFU slot.
  This will allow booting u-boot proper and then to fastboot/ums/dfu/...
  to flash.

Signed-off-by: Arnaud Patard <[email protected]>
```

On some systems, rebooting the system won't reset the memory content. This means that
booting over DFU after having done a boot from RAM will result in u-boot loading the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Arnaud,
thanks for adding a explanation and the solution to my problem.

I think the current explanation might mislead some users. U-Boot SPL will boot a U-Boot proper if it is present in RAM, whether it was put there by "boot from DFU" or by "boot from RAM".

This could lead some users that only use "boot from DFU" to not disable CONFIG_SPL_RAM_DEVICE.

We could maybe write something along the lines of: "This means that booting over DFU when there is already u-boot proper in RAM will boot the later and not download the new one from DFU, e.g. if you run snagrecover two times in a row, u-boot proper might not be updated in these cases"


The patches have been sent to the u-boot mailing list by their authors
and not yet merged. The patches can all be found inside this
[merge request](https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot/-/merge_requests/7).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch is using outdated U-Boot RAM-boot patches, please update the MR to use latest version of the series, at the moment v2. Also plan on sending a v3 with a small update next few days/week.


Snagboot can upload the ``CODE471_OPTION`` and ``CODE472_OPTION`` of a binary
generated with the ``boot_merger`` tool and configuration files from
[Rockchip rkbin](https://github.com/radxa/rkbin/tree/develop-v2024.03/).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably link to "upstream" https://github.com/rockchip-linux/rkbin tree.

Suggested change
[Rockchip rkbin](https://github.com/radxa/rkbin/tree/develop-v2024.03/).
[Rockchip rkbin](https://github.com/rockchip-linux/rkbin).


[example](../src/snagrecover/templates/rockchip-ramboot.yaml)

When building u-boot with the previously mentioned patches, u-boot will generate two files:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the latest U-Boot RK RAM-boot series you should build U-Boot with something like following to produce u-boot-rockchip-usb47X.bin files.

make <board>_defconfig rockchip-ramboot.config

At the end of the build, the following files will be needed:

- ``mkimage-in-simple-bin.mkimage-u-boot-tpl`` or ``mkimage-in-simple-bin.mkimage-rockchip-tpl``
- ``mkimage-in-simple-bin.mkimage-u-boot-spl``
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These mkimage-in-simple-bin.*-files are temporary files generated by binman during building of the final output u-boot-rockchip.bin-file.
This should probably not encourage users to rely on these files as they could be renamed and/or removed as part of a future update of U-Boot.

**code471:** File to use for maskrom code 0x471.

configuration:
* path: Path to the TPL file. For instance, ``mkimage-in-simple-bin.mkimage-rockchip-tpl``.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mkimage-in-simple-bin.mkimage-rockchip-tpl is a temporary file used by binman and may not be a good example.

if soc_model in NEWIDB_LIST:
return fw_blob

# Round to 4096 block size
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this padding to 4 KiB? Typically the boot image is padded to 512 or 2048 bytes.

Comment on lines +22 to +43
cfg = dev.get_active_configuration()

eps_found = False
for intf in cfg.interfaces():
ep_in, ep_out = None, None
for ep in intf.endpoints():
is_bulk = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK
is_in = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK
if not is_bulk:
continue
is_in = (ep.bEndpointAddress & usb.ENDPOINT_DIR_MASK) == usb.ENDPOINT_IN
if is_in:
ep_in = ep.bEndpointAddress
else:
ep_out = ep.bEndpointAddress
if not ((ep_in is None) or (ep_out is None)):
eps_found = True
break
if not eps_found:
raise RochipBootRomError("No BULK IN/OUT endpoint pair found in device")
self.ep_in = ep_in
self.ep_out = ep_out
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not really need the ep_in/ep_out for the ctrl_transfer done here, these endpoints are mostly needed for the RockUSB protocol, something that is not supported or used here.

Comment on lines +54 to +88
crc_sent = False
for chunk in utils.dnload_iter(blob, 4096):
chunk_len = len(chunk)
if chunk_len == 4096:
crc.process(chunk)
elif chunk_len == 4095:
chunk.append(0x00)
crc.process(chunk)
else:
crc.process(chunk)
crcbytes = crc.final()
chunk = bytearray(chunk)
chunk.append(crcbytes >> 8)
chunk.append(crcbytes & 0xff)
crc_sent = True
written = self.__write_chunk(code, chunk)
ret = written == len(chunk)
if ret is False:
return ret
total_written += written
if chunk_len+2 == 4096:
chunk = [0x00]
written = self.__write_chunk(code, chunk)
ret = written == len(chunk)
if ret is False:
return ret
if crc_sent is False:
chunk = bytearray()
crcbytes = crc.final()
chunk.append(crcbytes >> 8)
chunk.append(crcbytes & 0xff)
written = self.__write_chunk(code, chunk)
ret = written == len(chunk)
if ret is False:
return ret
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transfer loop can be simplified, please see my implementation at labgrid-project/labgrid#1721 for what I think is a cleaner and more simplified transfer loop.

dev = get_usb(usb_addr)

# Blob made with boot_merger
if "xpl" in recovery_config["firmware"]:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output from boot_merger is typically called loader-images, and could be a better name for this option.

xpl can be confused with U-Boot's use of xPL, i.e. all TPL/VPL/SPL phases prior to U-Boot proper.

path: mkimage-in-simple-bin.mkimage-u-boot-tpl
delay: 1
code472:
path: mkimage-in-simple-bin.mkimage-u-boot-spl
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted earlier, these example paths is for temporary files that should probably not be considered output artifacts from a U-Boot build.

@dsseng
Copy link

dsseng commented Sep 29, 2025

FYI, v3 patch set: https://lists.denx.de/pipermail/u-boot/2025-August/595680.html, @Kwiboo thanks for this and feel free to correct me if there's a newer series

I tested this U-Boot series on RV1106 (my branch) and it's really neat to boot from RAM with FIT attached (no need in SPL DFU) and all the bundling is done by U-Boot in-tree FOSS tools. I managed to use mass storage over DWC3 then, works great.

Also, might be interesting: https://github.com/collabora/rockchiprs/tree/main

Seems to be one of the most straightforward implementations, also somehow avoids those SoC support lists and perhaps autodetects RC4 mode. Might be worth taking a look, I was going to base on this design before I saw this PR.

I could possibly try to help on this if you would like, feel free to ask.

@Kwiboo
Copy link

Kwiboo commented Oct 2, 2025

https://lists.denx.de/pipermail/u-boot/2025-August/595680.html, @Kwiboo thanks for this and feel free to correct me if there's a newer series

Thanks and this should be the latest posted version.

I will most likely send a v4 with a small update to reduce size and use relocation as mentioned in labgrid-project/labgrid#1721

The the crc16 validation done by BootROM can be very slow, to optimize U-Boot RAM boot times using usb471/usb472 images I am exploring options to pack the FIT payload directly following SPL and then relocate the FIT payload before SPL try to load images from FIT.

@dsseng
Copy link

dsseng commented Oct 2, 2025

crc16 validation done by BootROM can be very slow

Ah, that's the thing I faced. I wondered why was it taking like 30 seconds for me, despite all transfers being complete. Maybe then SPL DFU is worth it, as that could be faster. Will try to make this work on my rv1106 when I'm back at it (I tried, but IIRC there was some effort needed like enabling the PHY in SPL or some clocks).

Thanks, I'll perhaps take a look if I can also enable FIT compression to make myself iterate more quickly in my U-Boot porting work

p.s. I've emailed you about my RV1106 progress, could you please share your thoughts or link me to communities where I can get more involved as a beginner U-Boot/Linux upstreaming developer? Sorry if you have already read the email and just haven't replied yet, I thought the message might have got to spam folder.

@rgantois
Copy link
Collaborator

rgantois commented Oct 5, 2025

Hello @apatard , it's been a few months since this PR saw updates, and it seems like quite a few review comments have been accumulating. Do you have any news on this? It would be quite nice if we could get this integrated before the upcoming release :)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rockchip support

7 participants