Compartilhar via


Atualização de firmware do dispositivo de banda larga móvel

Este artigo fornece diretrizes para fabricantes de módulos de Banda larga móvel (MB) que pretendem dar suporte a dispositivos de atualização de firmware por meio do Windows Update (WU). Os dispositivos devem estar em conformidade com a Especificação USB NCM Modelo de Interface de Banda Larga Móvel (MBIM) V1.0 lançado pelo Grupo de Trabalho de Dispositivos USB-IF.

As informações neste artigo se aplicam a:

  • Windows 8/Windows 10/Windows 11

Requisitos do dispositivo

Para dar suporte a atualizações de firmware na Banda Larga Móvel usando o Windows Update, os fabricantes de módulos ou dispositivos precisam estar em conformidade com os seguintes requisitos:

  • Driver baseado em UMDF (User Mode Driver Framework) desenvolvido pelo fabricante do módulo ou dispositivo, empacotado junto com o arquivo INF e o conteúdo do firmware. O arquivo INF de amostra e os detalhes são fornecidos na parte posterior deste documento
  • Firmware do dispositivo para implementar as seguintes funcionalidades:
    • Serviço de dispositivo de ID de firmware (FID). Para obter mais informações, consulte Serviço de dispositivo FID.
    • Firmware para dar suporte a um serviço de dispositivo de atualização de firmware. Esse é um serviço de dispositivo específico do fabricante do dispositivo que habilita que um driver UMDF chame e execute/baixe o conteúdo do firmware e inicie o processo de atualização do firmware.

Visão geral operacional

O diagrama a seguir mostra o design de alto nível e a interação entre os três componentes envolvidos: dispositivo MBIM, sistema operacional Windows 8 e driver de atualização de firmware fornecido pelo IHV.

Diagrama que mostra a interação entre o dispositivo MBIM, o sistema operacional Windows 8 e o driver de atualização de firmware fornecido pelo IHV.

  • Quando o Serviço WWAN detecta a chegada de um novo dispositivo MB, ele verifica se o dispositivo suporta o Serviço de Dispositivo de ID de Firmware (FID). Se estiver presente, ele recuperará o FID, que é definido como GUID. A especificação do Serviço de Dispositivo de Firmware que o IHV precisa para o suporte no dispositivo é descrita abaixo.
  • O Serviço WWAN (sistema operacional Windows) gera "nó de dispositivo flexível" usando o FID obtido acima como a ID de hardware do dispositivo. Isso é conhecido como "Nó de Desenvolvimento Flexível" no diagrama acima. A criação do nó de desenvolvimento iniciará o subsistema PnP (sistema operacional Windows) para encontrar o driver mais adequado. No Windows 8, o sistema PnP primeiro tentará instalar um driver do repositório local, se houver um disponível, e no sistema operacional paralelo tentará buscar um driver mais adequado do WU. O driver NULL da caixa de entrada será usado como padrão se o driver de melhor correspondência não estiver disponível para eliminar o problema "Driver não encontrado".
  • O pacote IHV WU, com base na correspondência FID, é extraído para o computador e instalado. Espera-se que o FID represente um SKU de firmware exclusivo (a exclusividade aqui é definida pela combinação de dispositivo VID/PID/REV e MNO). O pacote WU conteria um driver UMDF criado por IHV, bem como uma carga de firmware.
  • Depois que o UMDF do IHV é carregado no nó de desenvolvimento flexível, ele é responsável por controlar o fluxo de atualização do firmware. Deve-se notar que o tempo de vida do nó de desenvolvimento flexível está vinculado à presença física do dispositivo MBIM. O driver UMDF deve executar as seguintes etapas para executar atualizações de firmware
    • É aceitável que o dispositivo seja reinicializado várias vezes durante o processo de atualização do firmware, mas faria com que o driver UMDF fosse descarregado/recarregado
    • Todo o processo de atualização do firmware, incluindo reinicializações, não deve levar mais de que 60 segundos.
    • Depois que a atualização do firmware for concluída e o dispositivo for revertido para o modo MBIM, o Windows deverá ser notificado. Isso é feito limpando a propriedade DEVPKEY_Device_PostInstallInProgress definida anteriormente. A interface IWDFUnifiedPropertyStore descreve como definir uma propriedade no nó de desenvolvimento. Uma propriedade definida anteriormente pode ser limpa usando DEVPROP_TYPE_EMPTY.
    • Durante o retorno de chamada UMDF OnPrepareHardware, o driver UMDF deve verificar se o firmware no dispositivo precisa ser atualizado. Isso é feito comparando a versão do firmware no dispositivo com a que veio por meio do Windows Update. Orientações adicionais são fornecidas posteriormente no documento sobre o local de posicionamento do binário de firmware. Se a atualização do firmware for necessária, o driver UMDF deverá:
      • Agende um item de trabalho. A atualização real do firmware ocorre no contexto do item de trabalho.
      • Depois que o item de trabalho for agendado com êxito, notifique o Windows sobre o início da atualização do firmware. Isso é feito definindo a propriedade DEVPKEY_Device_PostInstallInProgress no nó de desenvolvimento flexível no contexto do retorno de chamada UMDF OnPrepareHardware.
      • É importante não bloquear o retorno de chamada OnPrepareHardware enquanto a atualização do firmware estiver em andamento. Espera-se que o retorno de chamada OnPrepareHardware seja concluído em um ou dois segundos, no máximo.

Arquivo INF de exemplo para o pacote WU

Esta seção fornece um INF de exemplo que faz parte do pacote WU. Os principais pontos a serem observados no arquivo INF são:

  • Os binários de firmware são independentes do driver UMDF.
  • Os binários de firmware estão localizados no diretório driverstore, um caminho determinado pelo sistema operacional e referenciado no INF usando DIRID 13. Os binários não podem ser arquivos executáveis contendo cabeçalhos PE/COFF.
  • %13%\<UniqueBinaryName>.bin
  • O arquivo INF armazena esse local no registro e o driver UMDF lê o valor do registro para descobrir o local binário.
  • O modelo INF de exemplo a seguir destaca os itens que precisam ser preenchidos pelo 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"

Serviço de Dispositivo de Identificação de Firmware (Serviço de Dispositivo FID)

O dispositivo compatível com MBIM implementará e relatará o seguinte serviço de dispositivo quando consultado por CID_MBIM_DEVICE_SERVICES. Os serviços conhecidos existentes são definidos na especificação MBIM do NCM na seção 10.1. A Microsoft Corporation estende isso para definir o serviço a seguir.

Nome do serviço = ID de firmware da Microsoft

UUID = UUID_MSFWID UUID

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

Especificamente, o seguinte CID é definido para o serviço de dispositivo UUID_MSFWID:

CID = CID_MBIM_MSFWID_FIRMWAREID

Código de comando = 1

Consulta = Sim

Conjunto = Não

Evento = Não

Definir carga do InformationBuffer = N/D

Carga da consulta QueryInformationBuffer = N/D

Conclusão da carga InformationBuffer = UUID

CID_MBIM_MSFWID_FIRMWAREID

O comando retorna a ID de firmware atribuída ao MNO ou IHV para o dispositivo. O UUID é codificado com base nas diretrizes da especificação MBIM.

Consulta = InformationBuffer no MBIM_COMMAND_MSG não usado. UUID retornado no InformationBuffer MBIM_COMMAND_DONE.

Definição = Sem suporte.

Evento não solicitado = Sem suporte

Trechos de código para o comportamento do driver UMDF

Conforme indicado anteriormente, o driver UMDF deve indicar ao Windows quando ele inicia e conclui a atualização do firmware. Esta seção fornece trechos de código que mostram como o driver deve notificar o Windows sobre esses 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;
}