Skip to content

UsbDFU mode - #2001

Draft
Aaron (apop5) wants to merge 4 commits into
microsoft:release/202608from
apop5:personal/apop5/usb
Draft

Aaron (apop5) wants to merge 4 commits into
microsoft:release/202608from
apop5:personal/apop5/usb

Conversation

@apop5

@apop5 Aaron (apop5) commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Description

The 202608 edk2 UsbBusDxe, on UsbPortReset, updated endpoint states,
read and discarded a fresh descriptor tree, then selected a configuration from
the cached descriptors (what interfaces that existed prior to the port reset).
This was done to prevent recursive connect calls.

It did not reconcile changed device identities or interface layouts with the installed UsbIo Protocol.
Changed device identities can occur for multiple
reasons. For the broken case we have, the identity is changed when a consumer
uses the UsbIo protocol to have the device enter DFU (device firmware update) mode
and the device exposes new interfaces after the next UsbPortReset call.

The resulting implementation refreshes compatible interfaces in place and
synchronously disconnects and replaces incompatible interfaces. It does not
connect function drivers from the reset path.

Reset behavior

For a configured, non-hub device:

  1. Guard against a nested reset or device removal.
  2. Reset the port and restore the address.
  3. Read fresh descriptors into temporary storage.
  4. If the device identity, interface count, default functions, and endpoints
    remain compatible, update the existing interface descriptor pointers.
  5. Otherwise, reject replacement during bus-owned driver binding or when the
    original caller TPL is above TPL_CALLBACK.
  6. Mark the physical device offline. Disconnect function drivers and their
    dependent children for every old interface, then uninstall USB I/O and
    Device Path protocols. Keep the old descriptor tree alive throughout teardown.
  7. Only after every old interface is removed, configure the new personality,
    adopt its descriptors, and publish its interfaces.
  8. Return without calling ConnectController() on the new interfaces.

The physical USB_DEVICE allocation and address remain in place. A successful
personality-changing reset invalidates all old USB I/O pointers, including the
one used to call reset. The caller must locate the new interface afterward.
The reset implementation does not dereference the removed interface after
teardown.

An unchanged-layout reset retains existing instances, including during driver
binding. Compatibility compares the standard device descriptor and default
interface classes and endpoint descriptors. It is not a byte-for-byte comparison
of all alternate settings or class-specific descriptors.

Supporting changes propagate configuration-teardown errors, avoid
freeing descriptors still referenced by partially published interfaces, and
stop port enumeration if the previous device could not be removed.
UsbDisconnectDriver() attempts disconnection even when the bus's cached
IsManaged flag is clear, so externally connected consumers are not skipped.
Connection and disconnection helpers preserve a caller already at or below
TPL_CALLBACK instead of unconditionally changing its TPL.

  • Impacts functionality?
  • Impacts security?
  • Breaking change?
  • Includes tests?
  • Includes documentation?

How This Was Tested

Ran on physical platform. Physical platform used UsbIo to send a device to
DFU mode. Then would attempt to locate the new UsbIo interface to send
a firmware update to the newly discovered DFU interface.

Prior to changes, the UsbIo DFU interface would not be found.
After the changes, the DFU interface was available.

Integration Instructions

No Integration necessary.

@mu-automation

mu-automation Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

✅ QEMU Validation Passed

Source Dependencies

Repository Commit
mu_basecore a60e089
mu_tiano_platforms 9a5b7f8

Results

Platform Target Build Boot Overall Boot Time Build Logs Boot Logs
Q35 DEBUG ✅ success ✅ success 0m 13s Build Logs Boot Logs
ArmVirt DEBUG ✅ success ✅ success 0m 14s Build Logs Boot Logs

Workflow run: https://github.com/microsoft/mu_basecore/actions/runs/40787462513

This comment was automatically generated by the Mu QEMU PR Validation workflow.

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 56.43564% with 88 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release/202608@003a16c). Learn more about missing BASE report.

Files with missing lines Patch % Lines
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c 62.00% 45 Missing and 12 partials ⚠️
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c 41.17% 30 Missing ⚠️
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                Coverage Diff                @@
##             release/202608    #2001   +/-   ##
=================================================
  Coverage                  ?    2.04%           
=================================================
  Files                     ?     1675           
  Lines                     ?   422965           
  Branches                  ?     6057           
=================================================
  Hits                      ?     8646           
  Misses                    ?   414193           
  Partials                  ?      126           
Flag Coverage Δ
FmpDevicePkg 9.63% <ø> (?)
MdeModulePkg 1.25% <56.43%> (?)
MdePkg 5.44% <ø> (?)
NetworkPkg 0.66% <ø> (?)
PolicyServicePkg 30.42% <ø> (?)
SecurityPkg 1.55% <ø> (?)
StandaloneMmPkg 0.50% <ø> (?)
UefiCpuPkg 4.70% <ø> (?)
UnitTestFrameworkPkg 11.70% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Add a googletest that will exercise the Runtime->Runtime interfaces
transition on UsbIo->UsbPortReset. Exercise the Runtime->DFU transition
on UsbPortReset and DFU->Runtime transition on UsbPortReset

if ((ConfigDesc == NULL) && (NewDev.DevDesc->Desc.NumConfigurations != 0)) {
ConfigDesc = NewDev.DevDesc->Configs[0];
Replace = TRUE;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Once you know Replace is TRUE, can you skip the rest of the checks?

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.

3 participants