Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La actualización de firmware del componente (CFU) es un protocolo y un proceso para enviar nuevas imágenes de firmware que se instalarán en el dispositivo de destino.
Nota:
CFU está disponible en Windows 10, versión 2004 (Actualización de mayo de 2020 de Windows 10) y versiones posteriores.
Los envíos de CFU al firmware residente son pares de archivos, un archivo es la parte de la oferta, el otro archivo es la parte de contenido. Cada envío de CFU (cada oferta y par de contenido) debe crearse fuera de línea antes de enviar el envío al firmware que implementa el proceso de CFU.
En el código fuente de firmware de ejemplo del repositorio de CFU en GitHub, el código común independiente de implementación general para CFU se encuentra en ComponentFwUpdate.c. Todos los demás archivos son archivos auxiliares que se pueden actualizar o modificar a la implementación única del desarrollador.
Contenido
- Las partes de oferta y contenido
Las partes de oferta y contenido
La oferta y el contenido componen un par de archivos en el esquema CFU.
La parte de la oferta es simplemente un archivo de 16 bytes de longitud que corresponde a la estructura FWUPDATE_OFFER_COMMAND descrita a continuación.
La parte de contenido, el firmware real que se va a actualizar está en el formato dictado por el desarrollador del usuario final. El código de ejemplo de CFU proporcionado usa archivos SREC para el contenido de firmware.
La oferta es una secuencia de 16 bytes. Esta estructura de oferta se integra en el archivo de oferta. Es básicamente datos binarios, no texto, porque la oferta contiene campos de bits de significado específico.
La oferta representada en el archivo se asigna a esta estructura en C:
typedef struct
{
struct
{
UINT8 segmentNumber;
UINT8 reserved0 : 6;
UINT8 forceImmediateReset : 1;
UINT8 forceIgnoreVersion : 1;
UINT8 componentId;
UINT8 token;
} componentInfo;
UINT32 version;
UINT32 hwVariantMask;
struct
{
UINT8 protocolRevision : 4;
UINT8 bank : 2;
UINT8 reserved0 : 2;
UINT8 milestone : 3;
UINT8 reserved1 : 5;
UINT16 productId;
} productInfo;
} FWUPDATE_OFFER_COMMAND;
De baja dirección a dirección alta, el primer byte de la oferta es un número de segmento.
<------- 4 bytes -----------> <-- 8 bytes --> <-------- 4 bytes --------->
+================================-=============================================+
| 15:0 7:3 2:0 7:6 5:4 3:0 31:0 31:0 7:0 7:0 7:7 6:6 5:0 7:0 |
| PI | R1 | MS | R0 | BK | PR | VM | VN | TK | CI | FV | FR | R0 | SN |
+================================-=============================================+
De la dirección más alta a la dirección más baja.
Byte(s) Value
---------------------------------------------------------
15:14 | (PI) Product ID is 2 bytes
13 | (R1) Reserved1 5-bit register
| (MS) Milestone 3-bit register
12 | (R2) Reserved2 2-bit register
| (BK) Bank 2-bit register
| (PR) Protocol Revision 2-bit register
11:8 | (VM) Hardware Variant Mask 32-bit register
7:4 | (VN) Version 32-bit register
3 | (TK) Token 8-bit register
2 | (CI) Component ID 8-bit register
1 | (FV) Force Ignore Version 1-bit register
| (FR) Force Immediate Reset 1-bit register
| (R0) Reserved0 6-bit register
0 | (SN) Segment Number 8-bit register
---------------------------------------------------------
Detalles del registro de ofertas
Id. de producto. Se puede aplicar un valor de identificador de producto único para esta imagen de CFU a este campo.
UINT16 productID;
El hito del firmware que representa el contenido de la oferta. Los hitos podrían ser versiones diferentes de la compilación de HW, por ejemplo, la compilación EV1, la compilación EV2, etc. La definición de hitos y la asignación de valores se dejan al desarrollador.
UINT8 milestone : 3;
Si el firmware está pensado para un banco específico, el campo de 2 bits admite cuatro bancos. El uso de un registro bancario se incluye en el formato de la oferta porque hay instancias en las que los dispositivos de destino usan regiones de firmware bancarias.
Si fuera así, y la oferta estaba pensada para actualizar un banco en uso, el firmware que implementa CFU en el destino puede rechazar la oferta. De lo contrario, el firmware en el destino que implementa CFU puede tomar otras medidas según sea necesario.
Si el almacenamiento de imágenes de firmware no está en el diseño del firmware del usuario final, es razonable omitir este campo (configurado en cualquier valor que sea conveniente, pero el valor en el campo de banco es opcional y depende de la forma en que el firmware de destino implemente el CFU).
UINT8 bank : 2;
La versión de protocolo del protocolo CFU que se usa se encuentra en 4 bits.
UINT8 protocolRevision : 4;
Máscara de bits correspondiente a todo HW único en el que puede funcionar esta imagen de firmware. Por ejemplo, la oferta puede indicar que se puede ejecutar en la versión X de hardware, pero no en la versión Y de hardware. La definición de bits y la asignación de valores se dejan al desarrollador.
UINT32 hwVariantMask;
Versión del firmware que se ofrece.
UINT32 version;
Token de bytes para identificar el software específico del usuario que realiza la oferta. Esto está pensado para diferenciar entre controladores y herramientas que pueden estar intentando actualizar el mismo firmware en ejecución. Por ejemplo, a un controlador de actualización CFU se le puede asignar el token 0xA y a una herramienta de actualización de desarrollo se le puede asignar el token 0xB. Ahora el firmware en ejecución puede optar de forma selectiva por aceptar o omitir comandos en función del proceso que intenta actualizarlo.
UINT8 token;
Componente del dispositivo para aplicar la actualización de firmware.
UINT8 componentId;
indicadores de interpretación de oferta: si queremos que el firmware in situ ignore el desajuste de versiones (más antigua sobre la más reciente), establezca el bit para forzar la omisión de la versión.
UINT8 forceIgnoreVersion: 1;
Un bit activa el forzamiento de un restablecimiento inmediato. Si ese bit está activado, el software del host espera que el firmware in situ provoque un reinicio del dispositivo. Las acciones del restablecimiento son específicas de la plataforma. El firmware del dispositivo puede optar por tomar medidas que cambien de bancos para que el firmware recién actualizado se convierta en el firmware activo in situ. O no. Se deja hasta la implementación del firmware. La expectativa suele ser que, si se afirma el reinicio inmediato por fuerza, el dispositivo hará lo que sea necesario para que el firmware actualice el nuevo banco y lo convierta en el firmware activo que se ejecuta en el dispositivo objetivo.
UINT8 forceImmediateReset : 1;
En caso de que la parte de contenido de la oferta y el par de contenido implique varias partes del contenido.
UINT8 segmentNumber;
Procesamiento de ofertas
ProcessCFWUOffer API acepta dos argumentos:
void ProcessCFWUOffer(FWUPDATE_OFFER_COMMAND* pCommand,
FWUPDATE_OFFER_RESPONSE* pResponse)
En este caso de uso, suponga que el software de usuario envía bytes de datos al firmware en ejecución y, a continuación, el primer mensaje es el mensaje de la oferta.
El mensaje de la oferta es un mensaje de 16 bytes descrito anteriormente (la estructura FWUPDATE_OFFER_COMMAND).
Ese mensaje de oferta es el dato utilizado por el firmware en ejecución para gestionar la oferta.
Durante la disposición de la oferta, el firmware en ejecución notifica al remitente rellenando los campos de la FWUPDATE_OFFER_RESPONSE estructura.
Interpretación de la oferta
El firmware en ejecución debe realizar un seguimiento de su estado en el proceso de CFU. Puede estar listo o esperando para aceptar una oferta, en medio de una transacción de CFU, o esperando para intercambiar bancos de memoria entre firmware activo/inactivo.
Si el firmware en ejecución está en medio de una transacción de CFU, no acepte ni procese esta oferta y notifique al host según corresponda.
if (s_currentOffer.updateInProgress)
{
memset(pResponse, 0, sizeof (FWUPDATE_OFFER_RESPONSE));
pResponse->status = FIRMWARE_UPDATE_OFFER_BUSY;
pResponse->rejectReasonCode = FIRMWARE_UPDATE_OFFER_BUSY;
pResponse->token = token;
return;
}
El campo de ID del componente de la oferta se puede usar para informar al firmware en ejecución que se solicita una acción especial. En el código CFU de ejemplo, el host usa un comando de oferta especial para recuperar el estado del motor CFU, si el software en ejecución es capaz y está listo para aceptar ofertas de CFU.
else if (componentId == CFU_SPECIAL_OFFER_CMD)
{
FWUPDATE_SPECIAL_OFFER_COMMAND* pSpecialCommand =
(FWUPDATE_SPECIAL_OFFER_COMMAND*)pCommand;
if (pSpecialCommand->componentInfo.commandCode == CFU_SPECIAL_OFFER_GET_STATUS)
{
memset(pResponse, 0, sizeof (FWUPDATE_OFFER_RESPONSE));
pResponse->status = FIRMWARE_UPDATE_OFFER_COMMAND_READY;
pResponse->token = token;
return;
}
}
Por último, se realiza una comprobación si hay un intercambio bancario pendiente. El intercambio bancario hace referencia al firmware que conserva la información sobre si todavía está en proceso de cambiar de la aplicación activa en ejecución a la imagen recién descargada.
Cómo y dónde se realiza el cambio bancario es una tarea específica de implementación para el firmware insertado. El protocolo y el proceso de CFU permiten intercambiar información entre la aplicación de usuario remoto que lleva a cabo el CFU y el firmware in situ que se está ejecutando.
else if (s_bankSwapPending)
{
memset(pResponse, 0, sizeof (FWUPDATE_OFFER_RESPONSE));
pResponse->status = FIRMWARE_UPDATE_OFFER_REJECT;
pResponse->rejectReasonCode = FIRMWARE_UPDATE_OFFER_SWAP_PENDING;
pResponse->token = token;
return;
}
Por último, si el estado del firmware en ejecución no está ocupado y el componentId no es un comando especial y no hay ningún intercambio bancario pendiente: ENTONCES podemos procesar esta oferta.
El procesamiento de una oferta implica, pero no se limita a, los cuatro pasos que se describen a continuación:
Paso 1: Comprobar banco
Compruebe el banco asociado con la aplicación en ejecución con el banco proporcionado en la oferta. ¿Son iguales o diferentes?
Si es lo mismo, rechace la opción (no queremos sobrescribir la imagen que está en ejecución o activa).
Si no, continúe.
Paso 2: Comprobar hwVariantMask
El firmware en ejecución comprueba la oferta en hwVariantMask contra el hardware en el que se ejecuta. Esto permite que el firmware insertado rechace una oferta si la oferta no es válida para el destino. (por ejemplo, si el firmware en ejecución está en una compilación anterior de HW y el nuevo firmware ofrecido está diseñado para una compilación más reciente, HW, entonces el firmware en ejecución debe rechazar esta oferta).
Si no es válido, rechace la oferta.
De lo contrario, continúe.
Paso 3: Comprobación de la versión del firmware
Compruebe si la versión del contenido de firmware que se ofrece tiene una versión anterior o más reciente que el firmware de la aplicación actual.
Se deja que la implementación de los usuarios decida cómo comprobar qué firmware es mayor que otro y si se permite usar el campo "forceIgnoreVersion" de la oferta. El desarrollo típico de firmware permitiría usar el campo "forceIgnoreVersion" durante el desarrollo del producto y en versiones de depuración del firmware, pero no se permitiría (no se permite que el firmware anterior sea actualizado sobre el firmware nuevo) en el firmware de producto o de lanzamiento.
Si se produjo un error en esta comprobación, rechace la oferta.
Si no, continúe.
Paso 4: Aceptar oferta
La oferta es buena. Acepte la oferta con una respuesta adaptada a la forma en que el firmware devuelve los mensajes y el estado a la aplicación de usuario remota. La llamada "respuesta" son datos (una estructura de datos empaquetada como se muestra en los archivos de encabezado de demostración) y estos datos se escriben en la aplicación de usuario a través de los medios adecuados para el dispositivo.
Procesamiento del contenido
El procesamiento del contenido suele ser un proceso de varios pasos. Los varios pasos hacen referencia a la funcionalidad del firmware para aceptar la imagen de firmware en partes, también conocidas como "bloques" de datos. No siempre es factible enviar toda la imagen a la vez al firmware incrustado, por lo que es realista esperar la implementación del protocolo CFU y el proceso para aceptar contenido en pequeños fragmentos.
En esta explicación se usa la suposición al describir el proceso del contenido de la CFU.
La máquina de estado del procesamiento de contenido implica tres estados.
Estado del procesamiento del primer bloque.
Estado del procesamiento del último bloque.
Estado del procesamiento de cualquier bloque entre el primero y el último.
Estructura del comando de contenido
Al igual que la oferta, el contenido tiene una estructura con campos que usan los algoritmos de CFU en la demostración.
typedef struct
{
UINT8 flags;
UINT8 length;
UINT16 sequenceNumber;
UINT32 address;
UINT8 pData[MAX_UINT8];
} FWUPDATE_CONTENT_COMMAND;
La estructura del comando de contenido es más sencilla que la estructura de la oferta. El contenido se define como una secuencia de bytes que se va a escribir en la memoria. El preámbulo del contenido es los campos de esta estructura:
UINT8 flagsIndica si el "bloque" de contenido es el primero, último u otro.UINT8 lengthMarca la longitud delpDatacampo. En el código de demostración de CFU, el límite del tamaño depDataes de 255 bytes. Otras implementaciones pueden variar el tamaño máximo del "bloque".UINT16 sequenceNumberMarca el contador del índice del bloque que se está enviando como contenido.UINT32 addressDesplazamiento de dirección del bloque. En la demostración de CFU de esta versión, la implementación tiene información predefinida sobre la dirección física de cada región de la aplicación. Por ejemplo, una implementación de firmware de dos bancos puede hacer que App1 comience en la dirección0x9000y App2 comience en la dirección0xA0000. Por lo tanto, dependiendo de cómo se preparó la imagen de firmware (S-Records), la dirección en el SREC puede ser la dirección física o un desplazamiento. En cualquier caso, debe haber una comprensión compartida entre la preparación del contenido y las rutinas específicas de implementación del procesamiento de contenido de CFU para determinar la verdadera dirección física de dónde escribir el bloque en memoria. Se deja que el desarrollador de firmware adopte los procedimientos recomendados y realice comprobaciones de intervalos de direcciones válidos para cada blog de contenido. Por ejemplo, el código CFU muestra una comprobación realizada si quizás App1 (destinado a0x9000) tiene direcciones que se superponen en App2, etc.UINT8 pData[MAX_UINT8]- Son los datos sin procesar del bloque de imagen del firmware. Se tiene cuidado en la aplicación de usuario para colocar sololengthbytes en el flujo de bytes completo del bloque de contenido.
No hay campos de bits usados en la estructura de contenido según la demostración de CFU del código proporcionado.
Primer bloque
El primer bloque inicia la descarga del contenido del firmware. El firmware que ejecuta intenta escribir el bloque en memoria no volátil. Por supuesto, el contenido "bloque" contiene información sobre dónde debe escribirse el bloque en la memoria, cuánto datos se van a escribir y otros campos.
Cada dispositivo de destino componentID es diferente y hay varios métodos para conservar los datos en la memoria. Por ejemplo, un componentId podría requerir escribir en flash interno, otro componentId puede escribir en un flash SPI externo u otro puede usar el protocolo I2C de otro IC para actualizar su imagen. La demostración incluida con este documento resalta el uso de una función denominada ICompFwUpdateBspWrite que cada firmware único debe implementar con conocimiento de las funciones de E/S de memoria no volátil subyacentes del destino para el que se diseñó.
Cualquier otro bloque excepto el primero o el último
El proceso de aceptar nuevos bloques continúa cuando la aplicación de usuario entrega otro bloque, de nuevo con metadatos en el mensaje para la dirección de dónde se debe escribir el bloque, cuántos bytes están contenidos y otros campos.
El firmware in situ trataría esto como un escenario de primer bloque.
Sin embargo, debe tenerse en cuenta que, si el sistema no logra capturar y almacenar el bloque en la memoria, corresponde al firmware in situ responder con un código de fallo.
Último bloque
El último bloque presenta un desafío solo si el firmware in situ necesita realizar tareas para validar la imagen que se acaba de escribir en la memoria.
En primer lugar, el último bloque se escribe en la memoria.
A continuación, como mínimo, se debe realizar una comprobación de CRC entre los datos ya escritos en la memoria (de los primeros a los últimos bloques) en comparación con el campo CRC en el último bloque. Se deja que cada firmware de implementación sepa cómo adquirir el CRC para la imagen descargada.
Tenga en cuenta que la ejecución de la comprobación del CRC tarda tiempo. A diferencia del flujo normal de la ejecución de la CFU para la presentación de ofertas y bloqueos. El último envío de bloque, si incluye una verificación CRC, tendrá un cierto retraso simplemente por el hecho de que la verificación CRC puede examinar una gran región de memoria. Dependiendo del dispositivo de destino y otros factores, esto puede no ser un problema.
Importante
La comprobación CRC de la imagen entrante es opcional y se puede desactivar. Sin embargo, es recomendable implementar buenas prácticas, al menos para realizar esta comprobación. Se recomienda encarecidamente que en este momento del proceso de CFU se realicen otras acciones para garantizar la integridad de la imagen descargada. Algunas de estas acciones podrían incluir comprobar una parte "firmada" de la imagen o comprobar las cadenas de certificados de confianza u otros métodos recomendados para garantizar una imagen de firmware segura. Estos se dejan al desarrollador de firmware.
Limpiar después del último bloque
Ahora que se ha escrito el último bloque y se ha completado la comprobación de CRC, el firmware puede responder con un error si alguna parte de la validación falla.
De lo contrario, se espera que el proceso de CFU en el firmware responda con un estado correcto.
Restablecimiento forzado comprobado
La indicación de restablecimiento forzado en la oferta se utiliza para determinar si la Unidad de Control Microprogramada (MCU) del destino debe someterse a un restablecimiento (definido por el usuario).
Normalmente, cuando se fuerza un restablecimiento, la intención es hacer que la MCU realice un restablecimiento para que el banco de aplicaciones cambie. La actualización de las variables persistentes para indicar a qué imagen de firmware arrancar al reiniciar se deja al desarrollador de firmware.