evidence · 13.0 KiB

uboot-ums-build.txt

Committed at docs/evidence/uboot-ums-build.txt. This is what grounds the requirements that cite it.

Open raw source

Stage 1 with USB device mode: what the build produced and what was checked (tasks 2.1-2.5)
==========================================================================================
2026-09-22, solomon, worktree for the-card-is-flashed-over-usb-from-u-boot, nixpkgs
20b1ddd1aa5ace70c9468305030aa4f9ef79671b. Everything is pasted from build logs or from
commands run on the results. NOT A BOOT: this stage 1 has not been on a card.

What changed, and where
-----------------------
  nix/uboot-k230-ums.config   appended to k230_canmv_v3_defconfig by nix/uboot-k230.nix (extraConfig):
    CONFIG_USB_GADGET=y
    CONFIG_DM_USB_GADGET=y
    CONFIG_USB_GADGET_DWC2_OTG=y
    CONFIG_USB_GADGET_DOWNLOAD=y
    CONFIG_USB_GADGET_VENDOR_NUM=0x29f1
    CONFIG_USB_GADGET_PRODUCT_NUM=0x0230
    CONFIG_CMD_USB_MASS_STORAGE=y
    # CONFIG_USB_DWC2 is not set
  nix/patches/uboot-k230/0001-k230_canmv_v3-enable-usbotg0-as-a-peripheral.patch:
    /* The data USB-C, J3, is wired to usbotg0 (schematic: USB0_P/USB0_N to J3
     * A6/A7/B6/B7, with USB0_ID and USB0_VBUS). k230.dtsi leaves usbotg0
     * disabled unless CONFIG_CMD_DFU is set; say so explicitly instead, and as
     * a peripheral, so U-Boot's `ums` can present the TF card to a host there.
     * Other Canaan boards (mrt, lckfb, gt6700) carry the same override.
     */
    &usbotg0 {
    	status = "okay";
    	dr_mode = "peripheral";
    };
    
  Sources unchanged: the same u-boot-2022.10 tarball and the same SDK commit as before.

Three build attempts, two of which the plan did not foresee
-----------------------------------------------------------
1. Fragment appended, nothing else. Turning USB_GADGET on makes symbols visible that the
   defconfig never answered, and a non-interactive make dies in syncconfig:
     Enable USB fastboot gadget (USB_FUNCTION_FASTBOOT) [N/y/?] (NEW)
     Error in reading or end of file.
   Fix: nix/uboot-k230.nix runs 'make olddefconfig' after the append (postConfigure).
2. Configured, then Canaan's own addition to drivers/usb/gadget/dwc2_udc_otg.c -- code the
   old configuration never compiled -- fails under GCC 15.3.0:
     drivers/usb/gadget/dwc2_udc_otg.c:1117:72: error: passing argument 1 of 'readl' makes pointer from integer without a cast [-Wint-conversion]
     drivers/usb/gadget/dwc2_udc_otg.c:1119:68: error: passing argument 2 of 'writel' makes pointer from integer without a cast [-Wint-conversion]
   The lines (overlay, dwc2_udc_otg_probe, marked '// kendryte'):
         #define USB0_TEST_CTL3 (0x9158507cU)
         #define USB1_TEST_CTL3 (0x9158509cU)
         #define USB_DMPULLDOWN0 	(1<<8)
         #define USB_DPPULLDOWN0 	(1<<9)
         u32 usb_test_ctl3 = readl((usbotg_reg == 0x91500000)?USB0_TEST_CTL3:USB1_TEST_CTL3);
         usb_test_ctl3 &= ~(USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
         writel(usb_test_ctl3, (usbotg_reg == 0x91500000)?USB0_TEST_CTL3:USB1_TEST_CTL3);
   GCC 13 warned about this; GCC 14 made -Wint-conversion an error. A u32 register address
   converted to a pointer is well defined on rv64, and the SPL and U-Boot the board booted were
   compiled by GCC 15, so the fix is the narrowest one: KCFLAGS=-Wno-error=int-conversion
   (extraMakeFlags), not a GCC 13 pin for the whole tree and not a patch to the vendor driver.
3. Built. Kconfig's later-wins for the three symbols the fragment reassigns, as expected:
     .config:1727:warning: override: reassigning to symbol USB_GADGET
     .config:1728:warning: override: reassigning to symbol DM_USB_GADGET
     .config:1759:warning: override: reassigning to symbol USB_DWC2
     build flags: -j32 SHELL=/nix/store/svx59425zxp552p2b8gm11qj5r09b56i-bash-5.3p15/bin/bash DTC=/nix/store/yj48bn5mmzd
     drivers/usb/gadget/dwc2_udc_otg.c:1117:72: warning: passing argument 1 of 'readl' makes pointer from integer withou
     drivers/usb/gadget/dwc2_udc_otg.c:1119:68: warning: passing argument 2 of 'writel' makes pointer from integer witho
     SPL size check: spl/u-boot-spl.bin is 222816 bytes (0x36660) against CONFIG_SPL_SIZE_LIMIT=0x80000 (524288 bytes)

The result: nix build .#uboot-k230 -> /nix/store/r55379zj8d5vwgq35ckzcr6m8xidsd9j-uboot-k230_canmv_v3_defconfig-riscv64-unknown-linux-gnu-2022.10
------------------------------------------------------------------------------------------
  2.1  $ grep -E 'CONFIG_(CMD_USB_MASS_STORAGE|USB_GADGET|DM_USB_GADGET|USB_GADGET_DWC2_OTG|USB_GADGET_DOWNLOAD|USB_GADGET_VENDOR_NUM|USB_GADGET_PRODUCT_NUM|USB_FUNCTION_MASS_STORAGE)=' .config
       CONFIG_CMD_USB_MASS_STORAGE=y
       CONFIG_DM_USB_GADGET=y
       CONFIG_USB_GADGET=y
       CONFIG_USB_GADGET_VENDOR_NUM=0x29f1
       CONFIG_USB_GADGET_PRODUCT_NUM=0x0230
       CONFIG_USB_GADGET_DWC2_OTG=y
       CONFIG_USB_GADGET_DOWNLOAD=y
       CONFIG_USB_FUNCTION_MASS_STORAGE=y
  2.2  $ grep -E 'CONFIG_(USB_DWC2|USB_HOST|USB_HOST_ETHER|USB_ETHER_RTL8152|USB_STORAGE|CMD_USB|CMD_DFU)\b' .config
       # CONFIG_CMD_DFU is not set
       # CONFIG_USB_DWC2 is not set
       (USB host off, and every host-side class driver went with it; CMD_USB stays as a command with nothing under it)
  2.3  $ fdtget k230_canmv_v3.dtb /soc/usb-otg@91500000 status dr_mode; ... @91540000
       usb-otg@91500000   status=okay      dr_mode=peripheral
       usb-otg@91540000   status=okay      dr_mode=otg
  2.4  $ strings u-boot.bin | grep -E 'UMS|ums <'
       UMS disk %d
       UMS: LUN %d, dev %s %d, hwpart %d, sector %#x, count %#x
       Use the UMS [USB Mass Storage]
       $ riscv64-unknown-linux-gnu-nm u-boot | grep -E ' (do_usb_mass_storage|dwc2_udc_otg_probe|_u_boot_list_2_driver_2_(dwc2_udc_otg|usb_dwc2))$'
       000000000001e8aa t do_usb_mass_storage
       0000000000044640 t dwc2_udc_otg_probe
       0000000000096a80 D _u_boot_list_2_driver_2_dwc2_udc_otg
       The ums command, the gadget driver's probe and its linker-list entry are in; the host driver's entry
       (_u_boot_list_2_driver_2_usb_dwc2) is not, so design D3's binding conflict cannot arise in this binary.
  Sizes: u-boot.bin 690280 bytes (was 721392 without the gadget and with USB host),
         spl/u-boot-spl.bin 222816 bytes (unchanged; nothing here touches the SPL).

nix build .#stage1 -> /nix/store/7s8fkshr67s6impk0syb9y2dl7xsfm54-k230-stage1
-----------------------------------------------------------------------
  $ cat result-stage1/SHA256SUMS
    fe3d537f62c34a3d01127c58fef4caec50f0e65b0192670712ecb1599584a954  fn_u-boot-spl.bin
    bd562f2bcff46ba9352061b08074f19df2f17dd0ca080293b47c20e3f5a6e50e  fn_ug_u-boot.bin
    cf108755a3cf3a8070a2f0ded84af672108e2301dfd58e5c2aa6a7555dbbd352  env.env
    74d08f8701dc72ea166d74be62fc3e5bff437d7c73ab68ad2f113cab289c38f9  fw_jump.bin
    9627edbeea9b115d7040beea27cc61b23b6aca61cd502fd7760d7ee179f42c99  fw_jump_add_uboot_head.bin
  Against the stage 1 the board booted (docs/evidence/stage1-from-source.txt): fn_u-boot-spl.bin, env.env,
  fw_jump.bin and fw_jump_add_uboot_head.bin are byte-identical; only fn_ug_u-boot.bin changed
  (805bd543... -> bd562f2bcff46ba9...). fn_ug_u-boot.bin is 350046 bytes against its 1 MiB slot.
  $ xxd -s 596 -l 4 result-stage1/fn_ug_u-boot.bin      (gzip magic, CM 09 -- the packaging is unchanged)
    00000254: 1f8b 0900                                ....

nix build .#sdImage (pure) -> /nix/store/8jpkdpxmhyysafqv5gk8vcimw347ikqq-k230-sd-image.img  (task 2.5)
-----------------------------------------------------------------------------------------
  Built without failing nix/sd-image.nix's slot checks. The three raw files against their slots:
    fn_u-boot-spl.bin      223348 bytes  in a  524288-byte slot
    fn_ug_u-boot.bin       350046 bytes  in a 1048576-byte slot
    env.env                  8192 bytes  in a  131072-byte slot
  (fn_ug_u-boot.bin is 350 046 bytes -- smaller than the 361 896 without the gadget, because
  USB host and its Ethernet class drivers left the binary with CONFIG_USB_DWC2.)
  $ sha256 over each slot of the image, for the file's length:
    0x100000  fe3d537f62c34a3d01127c58fef4caec50f0e65b0192670712ecb1599584a954  = fn_u-boot-spl.bin (the SPL the board booted)
    0x200000  bd562f2bcff46ba9352061b08074f19df2f17dd0ca080293b47c20e3f5a6e50e  = fn_ug_u-boot.bin (new: ums)
    0x300000  cf108755a3cf3a8070a2f0ded84af672108e2301dfd58e5c2aa6a7555dbbd352  = env.env
  This is the image task 3.1 would write to the card. Not written, not booted.

tools/flash-latest.sh --ums  (task 4.1), dry runs only
-------------------------------------------------------
  $ ./tools/flash-latest.sh --dry-run                         # the reader path, unchanged
    image: /nix/store/8jpkdpxmhyysafqv5gk8vcimw347ikqq-k230-sd-image.img
    stage 1: built from source by this flake (nix/stage1.nix)
    dry run: not flashing /dev/disk/by-id/usb-Generic-_USB3.0_CRW_-SD_201506301013-0:1     rc=0
  $ ./tools/flash-latest.sh --ums /dev/disk/by-id/whatever    # --ums discovers its own target
    error: --ums finds its own target; do not pass one     rc=1
  $ ./tools/flash.sh <image> /dev/sdz                         # flash.sh's guardrail, still there
    error: refusing a bare device node.     rc=1
  What --ums does when it is used for real (not exercised: no gadget has enumerated yet): snapshot
  /dev/disk/by-id/usb-* whole disks, build, wait up to 300 s for exactly one new entry, hand that by-id
  path to tools/flash.sh. flash.sh then prints the target's contents and asks for the path's last 12
  characters, as it does for a reader.

USB host and UMS coexistence stage 1 — build-host evidence only (task 6.1)
----------------------------------------------------------------------------
Source commit `5133502` adds the gadget driver's bind-time `-ENODEV` refusal
for non-peripheral/non-OTG DWC2 nodes, marks `usbotg1` as a host, and restores
`CONFIG_USB_DWC2`. On 2026-09-22, `nix build .#stage1` with only
`https://cache.nixos.org`, `--max-jobs 2`, and `--cores 8` built three
derivations and exited 0 in 22.345 seconds:

  stage 1: /nix/store/g8r05lrfbb8gcwh1m1nrfy6q870y7mh1-k230-stage1
  U-Boot:  /nix/store/324sxp64hh9xc7g5pp6izana9c3n1d0v-uboot-k230_canmv_v3_defconfig-riscv64-unknown-linux-gnu-2022.10

The actual generated `.config`, rather than the source fragment, contains:

  CONFIG_USB_DWC2=y
  CONFIG_USB_GADGET=y
  CONFIG_DM_USB_GADGET=y
  CONFIG_USB_GADGET_DWC2_OTG=y
  CONFIG_CMD_USB_MASS_STORAGE=y

The U-Boot-embedded DTB reports both intended assignments:

  /soc/usb-otg@91500000  status=okay  dr_mode=peripheral
  /soc/usb-otg@91540000  status=okay  dr_mode=host

`strings` over the built uncompressed U-Boot contains the `UMS: LUN` command
text. The raw stage-1 files fit their image slots:

  fn_u-boot-spl.bin 223348 bytes  <= 524288 bytes
  fn_ug_u-boot.bin  380844 bytes  <= 1048576 bytes
  env.env             8192 bytes  <= 131072 bytes

Their SHA-256 hashes are `fe3d537f62c34a3d01127c58fef4caec50f0e65b0192670712ecb1599584a954`,
`84241c45dce5d5531240db044005eebfbed0d467fd6eb8026c3b822167b84c0a`, and
`cf108755a3cf3a8070a2f0ded84af672108e2301dfd58e5c2aa6a7555dbbd352`,
respectively. This is source/build evidence only. Task 6.2 remains unchecked:
it requires a board to show the RTL8152 host tree while the J3 UMS gadget is
present on the host.

USB host match-priority repair — build-host evidence only
----------------------------------------------------------
The first coexistence candidate (`5133502`, stage 1
`/nix/store/g8r05lrfbb8gcwh1m1nrfy6q870y7mh1-k230-stage1`) is retained as a
failed hardware diagnostic: it booted and UMS enumerated, but its
`docs/evidence/uboot-usb-host-coexist.txt` transcript shows no working host
controller and no `usbotg1` in `dm tree`. The source explains why. In this
U-Boot, `lists_bind_fdt()` handles the gadget bind's `-ENODEV` by continuing
the outer compatible-string loop, not by trying the next driver for the same
`snps,dwc2` compatible. With only that one compatible string, the host driver
was never considered.

Commit `b25702e` retains that bind guard and adds
`canaan,k230-usbotg-host` as usbotg1's first compatible, with a matching
entry in the DWC2 host driver's ID table. The host driver therefore matches
the first compatible before the gadget sees the generic fallback. On
2026-09-22, the repaired `nix build .#stage1` used only
`https://cache.nixos.org`, `--max-jobs 2`, and `--cores 8`; it built three
derivations and exited 0 in 22.782 seconds:

  stage 1: /nix/store/bsv0h6hx9w90iyzv3d7imzb5dbafw503-k230-stage1
  U-Boot:  /nix/store/0lnadpfx4bz99r5z1y22sfyq11wdj53w-uboot-k230_canmv_v3_defconfig-riscv64-unknown-linux-gnu-2022.10

The generated configuration still has `CONFIG_USB_DWC2=y`,
`CONFIG_USB_GADGET=y`, `CONFIG_DM_USB_GADGET=y`,
`CONFIG_USB_GADGET_DWC2_OTG=y`, and `CONFIG_CMD_USB_MASS_STORAGE=y`. Its
embedded DTB has:

  /soc/usb-otg@91500000  compatible=snps,dwc2  dr_mode=peripheral
  /soc/usb-otg@91540000  compatible=canaan,k230-usbotg-host,snps,dwc2  dr_mode=host

The resulting `fn_ug_u-boot.bin` is 380911 bytes in the 1 MiB slot, with
SHA-256 `4cb755ed0b0ac06fcccade582fcbc90f99ffb6f4c35cec65e3564804b5be6226`.
SPL, environment, OpenSBI, and wrapped OpenSBI retain their prior hashes.
This is source/build evidence only. The repair still requires the task 6.2
hardware proof; it does not claim that the host controller or packet traffic
works.