Compartir a través de


Actualización de firmware del dispositivo de banda ancha móvil

En este artículo se proporcionan instrucciones para los fabricantes de módulos de banda ancha móvil (MB) que tienen pensado admitir dispositivos de actualización de firmware a través de Windows Update (WU). Los dispositivos deben cumplir la especificación USB NCM Mobile Broadband Interface Model (MBIM) V1.0 publicada por el grupo de trabajo de dispositivos USB-IF.

La información de este artículo se aplica a:

  • Windows 8/Windows 10/Windows 11

Requisitos de los dispositivos

Para admitir actualizaciones de firmware en banda ancha móvil mediante Windows Update, los fabricantes de módulos o dispositivos deben cumplir los siguientes requisitos:

  • Controlador basado en UMDF (User Mode Driver Framework) desarrollado por el fabricante del módulo o del dispositivo, empaquetado junto con la carga de firmware y el archivo INF. Los detalles y el archivo INF de ejemplo se proporcionan en la última parte de este documento
  • Firmware del dispositivo para implementar las siguientes funcionalidades:
    • Servicio de dispositivo de ID de firmware (FID). Para obtener más información, consulte Servicio de dispositivo FID.
    • Firmware para admitir un servicio de dispositivo de actualización de firmware. Se trata de un servicio de dispositivo específico del fabricante de dispositivos que permite que un controlador UMDF llame y ejecute o descargue la carga del firmware e inicie el proceso de actualización de firmware.

Información general sobre el funcionamiento

En el diagrama siguiente se muestra el diseño y la interacción de alto nivel entre los tres componentes implicados: dispositivo MBIM, sistema operativo Windows 8 y controlador de actualización de firmware proporcionado por IHV.

Diagrama que muestra la interacción entre el dispositivo MBIM, el sistema operativo Windows 8 y el controlador de actualización de firmware proporcionado por IHV.

  • Cuando el servicio WWAN detecta la llegada de un nuevo dispositivo MB, comprueba si el dispositivo admite el servicio de dispositivo de ID de firmware (FID). Si está presente, recupera el FID, que se define como GUID. A continuación se describe la especificación del servicio de dispositivo de firmware que el IHV necesita para la compatibilidad en el dispositivo.
  • El servicio WWAN (SO Windows) genera el "nodo de dispositivo flexible" mediante el FID obtenido anteriormente como identificador de hardware del dispositivo. Esto se conoce como "nodo de desarrollo flexible" en el diagrama anterior. La creación del nodo de desarrollo iniciará el subsistema PnP (SO Windows) para encontrar el mejor controlador coincidente. En Windows 8, el sistema PnP intentará primero instalar un controlador desde el almacén local, si hay uno disponible, y en paralelo el sistema operativo intentará capturar un controlador que coincida mejor de WU. El controlador NULL de serie se usará como valor predeterminado si el controlador que mejor coincide no está disponible para eliminar el problema de "Driver Not Found".
  • El paquete WU de IHV, basado en la coincidencia de FID, se baja a la máquina y se instala. Se espera que el FID represente una SKU de firmware única (unicidad definida por el dispositivo de combinación VID/PID/REV y MNO). El paquete WU contendrá un controlador UMDF creado por IHV, así como una carga de firmware.
  • Una vez cargado el UMDF de IHV en el nodo de desarrollo flexible, es responsable de controlar el flujo de actualización de firmware. Debe tenerse en cuenta que el tiempo de vida del nodo de desarrollo flexible está vinculado a la presencia física del dispositivo MBIM. El controlador UMDF realizará los pasos siguientes para realizar actualizaciones de firmware.
    • Es aceptable que el dispositivo se reinicie varias veces durante el proceso de actualización de firmware, pero provocaría que el controlador UMDF se descargue o vuelva a cargar.
    • Todo el proceso de actualización de firmware, incluidos los reinicios, no debe durar más de 60 segundos.
    • Una vez completada la actualización del firmware y el dispositivo se ha revertido al modo MBIM, se debe notificar a Windows. Para ello, borre la propiedad DEVPKEY_Device_PostInstallInProgress establecida anteriormente. La interfaz IWDFUnifiedPropertyStore describe cómo establecer una propiedad en dev-node. Una propiedad establecida anteriormente se puede borrar mediante DEVPROP_TYPE_EMPTY.
    • Durante la devolución de llamada de UMDF ONPrepareHardware UMDF, el controlador UMDF comprobará si es necesario actualizar el firmware del dispositivo. Esto se hace comparando la versión del firmware en el dispositivo con la que llegó a través de Windows Update. Más adelante en el documento se proporcionan instrucciones adicionales sobre la ubicación del archivo binario de firmware. Si se requiere la actualización de firmware, el controlador UMDF debe:
      • Programar un elemento de trabajo. La actualización real del firmware se produce en el contexto del elemento de trabajo.
      • Una vez programado correctamente el elemento de trabajo, notifique a Windows el inicio de la actualización de firmware. Para ello, establezca la propiedad DEVPKEY_Device_PostInstallInProgress en el nodo de desarrollo flexible en el contexto de la devolución de llamada UMDF OnPrepareHardware.
      • Es importante no bloquear la devolución de llamada OnPrepareHardware mientras la actualización del firmware está en curso. Se espera que la devolución de llamada OnPrepareHardware se complete en un segundo o dos como máximo.

Archivo INF de ejemplo para el paquete WU

En esta sección se proporciona un INF de ejemplo que forma parte del paquete WU. Los puntos clave que se deben tener en cuenta en el archivo INF son:

  • Los archivos binarios de firmware son independientes del controlador UMDF.
  • Los archivos binarios de firmware se encuentran en el directorio driverstore, una ruta de acceso determinada por el sistema operativo y a la que se hace referencia en el INF mediante DIRID 13. Los archivos binarios no pueden ser archivos ejecutables que contengan encabezados PE/COFF.
  • %13%\<UniqueBinaryName>.bin
  • El archivo INF almacena esta ubicación en el Registro y el controlador UMDF lee el valor del Registro para detectar la ubicación del archivo binario.
  • En la plantilla INF de ejemplo siguiente se resaltan los elementos que debe rellenar el IHV.
[Version]
Signature       = "$WINDOWS NT$"
Class           = Firmware
ClassGuid       = {f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
Provider        = %Provider%
DriverVer       = 06/21/2006,6.2.8303.0
CatalogFile     = MBFWDriver.cat
PnpLockdown     = 1

[Manufacturer]
%Mfg%           = Firmware,NTx86

[Firmware.NTx86]
%DeviceDesc%    = Firmware_Install,MBFW\{FirmwareID}    ; From Device Service
;%DeviceDesc%    = Firmware_Install,MBFW\{2B13DD42-649C-3442-9E08-D85B26D7825C}

[Firmware_Install.NT]
CopyFiles       = FirmwareDriver_CopyFiles,FirmwareImage_CopyFiles

[Firmware_Install.NT.HW]
AddReg          = Device_AddReg

[Device_AddReg]
HKR,,FirmwareBinary,,"%13%\MBIHVFirmware-XYZ-1.0.bin"

[Firmware_Install.NT.Services]
AddService      = WUDFRd,0x000001fa,WUDFRD_ServiceInstall

[WUDFRD_ServiceInstall]
DisplayName     = %WudfRdDisplayName%
ServiceType     = 1
StartType       = 3
ErrorControl    = 1
ServiceBinary   = %12%\WUDFRd.sys
LoadOrderGroup  = Base

[Firmware_Install.NT.CoInstallers]
CopyFiles       = WudfCoInstaller_CopyFiles

[WudfCoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000,"WUDFCoinstaller.dll"

[Firmware_Install.NT.Wdf]
UmdfService      = MBIHVFirmwareDriver,MBIHVFirmwareDriver_Install
UmdfServiceOrder = MBIHVFirmwareDriver

[MBIHVFirmwareDriver_Install]
UmdfLibraryVersion  = 1.11
ServiceBinary       = %12%\UMDF\MBFWDriver.dll
DriverCLSID         = {<DriverClassGuid>} ; From UMDF driver

[FirmwareImage_CopyFiles]
MBIHVFirmware-XYZ-1.0.bin   ; Firmware Image

[FirmwareDriver_CopyFiles]
MBFWDriver.dll          ; UMDF driver for SoftDevNode

[DestinationDirs]
FirmwareImage_CopyFiles  = 13      ; Driver Store
FirmwareDriver_CopyFiles = 12,UMDF ;%SystemRoot%\System32\drivers\UMDF

[SourceDisksFiles]
MBIHVFirmware-XYZ-1.0.bin = 1

[SourceDisksNames]
1 = %DiskName%

; ================== Generic ==================================

[Strings]
Provider        = "MBIHV"
Mfg             = "MBIHV"
DeviceDesc      = "MBIHV Mobile Broadband Firmware Device"
DiskName        = "Firmware Driver Installation Media"

Servicio de dispositivo de identificación de firmware (servicio de dispositivo FID)

El dispositivo compatible con MBIM implementará e informará del siguiente servicio de dispositivo cuando se consulte mediante CID_MBIM_DEVICE_SERVICES. Los servicios conocidos existentes se definen en la especificación MBIM de NCM en la sección 10.1. Microsoft Corporation amplía esta opción para definir el siguiente servicio.

Nombre del servicio = ID de firmware de Microsoft

UUID = UUID_MSFWID UUID

Valor = e9f7dea2-feaf-4009-93ce-90a3694103b6

En concreto, el CID siguiente se define para el servicio de dispositivo UUID_MSFWID:

CID = CID_MBIM_MSFWID_FIRMWAREID

Código de comando = 1

Consulta =

Establecer = No

Evento = No

Establecer carga de InformationBuffer = N/A

Consultar carga de InformationBuffer = N/A

Finalización de carga de InformationBuffer = UUID

CID_MBIM_MSFWID_FIRMWAREID

El comando devuelve el identificador de firmware asignado de MNO o IHV para el dispositivo. El UUID se codifica en función de las directrices de la especificación MBIM.

Consulta = InformationBuffer en MBIM_COMMAND_MSG no se usa. UUID devuelto en InformationBuffer MBIM_COMMAND_DONE.

Establecer = No compatible

Evento no solicitado = No compatible

Fragmentos de código para el comportamiento del controlador UMDF

Como se indicó anteriormente, el controlador UMDF debe indicar a Windows cuándo se inicia y completa la actualización del firmware. En esta sección se proporcionan fragmentos de código que muestran cómo el controlador debe notificar a Windows estos eventos.

/**
 * This is the IPnpCallbackHardware*:OnPrepareHardware handler 
 * in the UMDF driver. This is called every time the firmware 
 * update is device is started. Since this handler should be 
 * blocked from returning actual the firmware update process 
 * should be done in a workitem 
 */
HRESULT
CMyDevice::OnPrepareHardware(IWDFDevice* pDevice)
{
    HRESULT hr = S_OK;
    BOOL bFirmwareUpdateInProgress = FALSE;
    BOOL bFirmwareUpdateNeeded = FALSE;
    BOOL bFirmwareUpdateIsDone = FALSE;

    //
    // The snippets below demonstrates the steps for firmware 
    // update against a MB device that loads the updated firmware 
    // on device boot. So the firmware update driver needs to
    // send the new firmware down to the device and then tell 
    // the device to initiate a stop/start. Once the device has
    // reappeared, it would have automatically loaded the 
    // new firmware
    // 


    //
    // First, determine if firmware update is in progress. This 
    // can be based on some registry key that is saved when
    // firmware update is started
    //

    // Assuming this status is returned in bFirmwareUpdateInProgress
    if (bFirmwareUpdateInProgress)
    {
        //
        // If firmware update is in progress, check if its done. For
        // this it may be necessary to access the MB device. Note that 
        // if the MB device (& hence the Firmware update device) needs
        // multiple stop/starts to do the firmware update. In that case
        // it will be marked as done at the end of the process
        //

        // Assuming this status is returned in bFirmwareUpdateIsDone
        if (bFirmwareUpdateIsDone)
        {
            //
            // Signal the completion of the firmware update
            // process.
            //
            SignalFirmwareUpdateComplete(pDevice);
        }
        else
        {
            //
            // Take appropriate steps to get notified when
            // firmware update is done. Call SignalFirmwareUpdateComplete
            // when that notification is received
            //
        }
    }
    else
    {
        //
        // Determine if firmware update is needed. This can be 
        // based on checking state in the registry of the last
        // firmware version set on the device to the firmware
        // version associated with this driver
        //
        
        // Assuming this status is returned in bFirmwareUpdateNeeded
        if (bFirmwareUpdateNeeded)
        {
            // 
            // Create and queue a workitem to perform the firmware
            // update process. IWDFWorkItem can be used for this
            //
            
            // Assuming the creation/enquing status
            // is returned in hr
            
            if (SUCCEEDED(hr))
            {
                //
                // Work item queued. It will do the firmware update
                // Tell the OS that firmware update is in progress
                //
                SignalFirmwareUpdateInProgress(pDevice);
            }
        }
    }

    //
    // If we have a failure, we clear the firmware update
    // in progress state
    //
    if (FAILED(hr))
    {
        SignalFirmwareUpdateComplete(pDevice);
    }
    return S_OK;
}

/**
 * This function tells the OS that firmware update is in progress.
 * It should be called from the firmware update UMDF driver's 
 * IPnpCallbackHardware*:OnPrepareHardware handler after it has
 * successfully queued a workitem to perform the firmware update
 */
HRESULT
CMyDevice::SignalFirmwareUpdateInProgress(
    __in IWDFDevice* pDevice
    )
{
    HRESULT hr = S_OK;    
    IWDFUnifiedPropertyStoreFactory* spPropertyStoreFactory = NULL;
    IWDFUnifiedPropertyStore* spPropStore = NULL;
    WDF_PROPERTY_STORE_ROOT wdfPropRoot = { sizeof(WDF_PROPERTY_STORE_ROOT), WdfPropertyStoreRootClassHardwareKey };
    DEVPROP_BOOLEAN boolValue = DEVPROP_TRUE;
    
    do
    {
       
        hr = pDevice->QueryInterface(IID_PPV_ARGS(&spPropertyStoreFactory));
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to query for property store factory. Error = 0x%x", hr);
            break;

        }
        
        hr = spPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(
            &wdfPropRoot,
            &spPropStore
            );
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to query for device property store. Error = 0x%x", hr);
            break;
        }

        // Set the OS flag
        hr = spPropStore->SetPropertyData(
            reinterpret_cast<const DEVPROPKEY*>(&DEVPKEY_Device_PostInstallInProgress),
            0, // this property is language neutral
            0,
            DEVPROP_TYPE_BOOLEAN,
            sizeof(DEVPROP_BOOLEAN),
            &boolValue
            );
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to set device property for PostInstallInProgress. Error = 0x%x", hr);
            break;
        }

        //
        // Save some state so that we know we are in the process
        // of firmware update
        //
    } while (FALSE);        

    if (spPropStore)
    {
        spPropStore->Release();
    }

    if (spPropertyStoreFactory)
    {
        spPropertyStoreFactory->Release();
    }

    return hr;
}


/**
 * This function tells the OS that firmware update is done
 * It should be called only after the full firmware update process
 * (including any MB device stop/start) has finished
 */
HRESULT
CMyDevice::SignalFirmwareUpdateComplete(
    __in IWDFDevice* pDevice
    )
{
    HRESULT hr = S_OK;    
    IWDFUnifiedPropertyStoreFactory* spPropertyStoreFactory = NULL;
    IWDFUnifiedPropertyStore* spPropStore = NULL;
    WDF_PROPERTY_STORE_ROOT wdfPropRoot = { sizeof(WDF_PROPERTY_STORE_ROOT), WdfPropertyStoreRootClassHardwareKey };
    
    do
    {
        hr = pDevice->QueryInterface(IID_PPV_ARGS(&spPropertyStoreFactory));
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to query for property store factory. Error = 0x%x", hr);
            break;

        }

        hr = spPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(
            &wdfPropRoot,
            &spPropStore
            );
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to query for device property store. Error = 0x%x", hr);
            break;
        }

        hr = spPropStore->SetPropertyData(
            reinterpret_cast<const DEVPROPKEY*>(&DEVPKEY_Device_PostInstallInProgress),
            0, // this property is language neutral
            0,
            DEVPROP_TYPE_BOOLEAN,
            0,
            NULL
            );
        if (FAILED(hr))
        {
            Trace(TRACE_LEVEL_ERROR, "Failed to clear device property for PostInstallInProgress. Error = 0x%x", hr);
            break;
        }

        //
        // Save some state so that we can do quick check on 
        // whether firmware update is needed or not
        //

    } while (FALSE);        

    if (spPropStore)
    {
        spPropStore->Release();
    }

    if (spPropertyStoreFactory)
    {
        spPropertyStoreFactory->Release();
    }

    return hr;
}