Cargador de arranque STM32: Cómo garantizar que solo arranques de firmware no corruptos

Tengo una placa personalizada con un STM32F407. Como SWD no está disponible, tengo que programar el microcontrolador a través del cargador de arranque UART.

Imagine que tiene lugar la siguiente secuencia de eventos. Levanto el BOOT0pin alto y después de reiniciar, el microcontrolador ingresa al cargador de arranque. A petición mía, el gestor de arranque borra la memoria flash del microcontrolador. Supongo que ahora todas las palabras en la memoria son 0xffffffff. Luego envío una secuencia de comandos de escritura para escribir el flash, comenzando en el primer byte de mi imagen de firmware y continuando hasta el último.

Si falla la alimentación o se pierde la comunicación en algún lugar de este proceso, tengo un microcontrolador que tiene una imagen de programa no válida en la memoria flash. Cuando el microcontrolador se vuelve a encender posteriormente, para BOOT0ejecutar la aplicación, ejecuta lo que es esencialmente un firmware corrupto. Según el comportamiento del programa y el hardware adjunto, los resultados podrían ser catastróficos.

No puedo encontrar ningún tipo de soporte para inhibir el inicio del firmware cuando hay una imagen corrupta en el STM32F407. Los mecanismos viables podrían ser una verificación de CRC antes de que la CPU salte al firmware o un bit de "inhibir el inicio del firmware" en flash que se establece (borra) primero durante el borrado y se borra (se escribe 0) al final del proceso de actualización. Sin embargo, no encuentro tales disposiciones en el hardware.

  • Escriba un cargador de arranque personalizado en Flash que debe programarse una vez. Los vectores de reinicio están configurados para saltar siempre al gestor de arranque personalizado. Ese comprueba la presencia y verifica la integridad del firmware. Con ese fin, el firmware debe incluir información de tamaño y suma de verificación en un lugar conocido por el gestor de arranque personalizado. Esta solución tiene la desventaja obvia de que requiere que consiga este cargador de arranque personalizado (escribiéndolo yo mismo o adaptando algo que ya existe) y que el cargador de arranque personalizado debe cargarse primero durante la producción.
  • Suponga que un flash borrado conduce a un bloqueo del procesador. Todavía no estoy tan convencido de que arrancar en un flash borrado provoque un bloqueo rápido. Incluso si el procesador se bloquea al iniciar el firmware, aún puedo activar el gestor de arranque tirando /RSThacia abajo, BOOT0hacia arriba y luego soltando /RST. Durante la actualización, después del borrado, el firmware se escribe comenzando justo después del par de vectores de reinicio inicial de SP/PC inicial. Como último paso de la actualización, los PC/SP iniciales se escriben en las dos primeras palabras de 32 bits de la memoria flash. La ventana crítica ahora es solo la escritura de estas dos palabras, lo que reduce la posibilidad de falla en órdenes de magnitud.

¿Cuáles son las estrategias sensatas para tratar el problema planteado? ¿Son viables las opciones presentadas anteriormente?

Agregue un cargador de arranque L1 persistente codificado por usted mismo que implementará la verificación de integridad.
Además, parece que el cargador de arranque STM32 tiene el comando "Obtener" que le permite leer los datos, para que pueda implementar la verificación en el host de programación.
Gracias, esta solución es la primera en mi lista de viñetas en la pregunta. ¿Conoce algún gestor de arranque de código abierto para la familia STM32 que encajaría bien aquí?
Desafortunadamente, verificar el contenido no es suficiente. Considere esto: Durante la actualización, se pierde energía. El microcontrolador ahora tiene un firmware incompleto. Cuando se le permita iniciar la próxima vez, se ejecutará desde una imagen de firmware corrupta.
¿Cuál es su resultado catastrófico y bajo qué circunstancias está actualizando el firmware?
El microcontrolador se encarga de controlar la maquinaria de alta potencia. El resultado catastrófico es que esta maquinaria funciona como consecuencia de un firmware corrupto, lo que provoca lesiones o la muerte. El firmware se puede actualizar como parte de una actualización de software del sistema envolvente a pedido del usuario.
En general, STM32 no está calificado para aplicaciones críticas para la seguridad. electronics.stackexchange.com/questions/427067/…
Entonces, necesita absolutamente al menos el cargador de arranque que realiza una verificación de CRC, puede haber otras fuentes de corrupción además de una actualización fallida.

Respuestas (2)

arrancar en un flash borrado conduce al bloqueo rápidamente

Esto puede suceder o no, según lo que se escribió y lo que no. Tenga en cuenta que, dependiendo de cómo se actualice el flash y el tiempo, es posible que no haya una página flash borrada, solo algunas con datos nuevos y otras con datos antiguos.

PC/SP inicial [...] La ventana crítica ahora es solo la escritura de estas dos palabras

Cierto, pero aún habrá una posibilidad de falla, no lo suficientemente bueno para aplicaciones críticas de seguridad.

Tenga en cuenta que los usuarios pueden tener la tentación de utilizar una herramienta de flasheo STM32 estándar en lugar de su software; funcionaría bien con el gestor de arranque de ROM, pero anulará sus mitigaciones por completo.

Escriba un gestor de arranque personalizado en Flash

Recomiendo encarecidamente este enfoque si los resultados pueden ser catastróficos en condiciones de falla.

su primera opción es trivial, el tiempo que ha esperado una respuesta aquí hasta ahora podría haber escrito sobre 30 cargadores de arranque diferentes. Ya respondió la pregunta, simplemente podría programar eso una vez que el cargador de arranque haga un CRC si tiene tiempo o una suma de verificación si tiene prisa y usarlo o no. puñados de código, minutos para escribir. Ahora, si no es el caso, está bien, podría ser un proyecto de investigación o al menos algunos experimentos bastante seguros de que ST documenta cómo iniciar el cargador de arranque, debería ser tan simple como bifurcarse a una dirección alta o más probablemente leer la dirección mágica alta más 4 y bx a esa dirección (entonces está en el cargador de arranque de fábrica y no tiene que escribir/reemplazar uno).

Hacer su propio cargador de arranque basado en uart no es difícil, en unas 30-50 líneas de código, tal vez un par de puñados más. ser más complicado que eso. puede tener uno que haga una dirección de protocolo, datos con algún marco alrededor como srec/ihex pero quizás diferente. otra media hora a una hora de desarrollo (bueno, más el tiempo para aprender a flashear en la aplicación, que es bastante fácil, creo que st lo explica).

Si desea escribir su propio cargador que pueda flashear, entonces desea un dispositivo de doble banco y el verificador/cargador está en un banco y la aplicación en el otro. O haces el trampolín del cargador para embestir. Estoy bastante seguro de que el tamaño de borrado en estas partes es una fracción de todo el flash, por lo que, incluso sin un flash de doble banco, podría saltar al ram y borrar lo que ha definido como espacio de aplicación solamente.

Puede configurar el bloque de borrado más bajo para tener la tabla de vectores con reinicio apuntando al verificador de arranque, puede tener su aplicación en vivo comenzando en el siguiente bloque de borrado si eso deja espacio para que el verificador de arranque crezca con el tiempo. Supongo que tiene el control de VTOR, por lo que no necesita meterse con los otros vectores, tenerlos sin salida en un bucle infinito en el verificador.

Ahora el rápido y sucio no tiene que hacer nada de esto pero aún ofrece algo de riesgo pero menos. Es que si se borra el extremo frontal de la tabla de vectores, se llama al cargador de arranque, ya debería haber visto esto con partes vírgenes que no tiene que afirmar boot0 con una parte nueva. Creo que son solo las primeras cuatro palabras, pero puedes resolver esto experimentalmente. Entonces, cuando descargue un nuevo firmware, cambie su programa para borrar primero el primer bloque con la tabla de vectores, lo que probablemente ya haya hecho, pero escriba ese bloque al final, borre y escriba el resto de la aplicación, escriba el primer bloque al final y solo ese período de el tiempo corre el riesgo de pérdida de energía o reinicio u otro evento que provoque una imagen corrupta.

Por último, podrías escribir un código perfecto que nunca necesite una actualización de firmware... sonríe... eso lo resolvería...

Estas son piezas COTS, por lo que no son críticas para la seguridad como se mencionó. Pero podría dedicar algunas horas de este esfuerzo adicional para ayudar a algunos.

Esto no significa necesariamente que si pierde energía o se reinicia en el momento adecuado, la parte no corrompe ni borra su cargador de arranque de respaldo, no ha leído los manuales flash tan de cerca, pero sabe que algunos eeproms solían funcionar de esa manera, si apagó correctamente o cronometró las cosas correctamente, podría perder datos. Las pruebas no probarían que nunca hay una manera de hacerlo, pero podría configurar un dispositivo de prueba para encender, iniciar una descarga/borrado y apagar la pieza en un momento aleatorio, repetir. Repita antes del número anunciado de ciclos de flash para la pieza. Cada vez que verifique que el verificador de arranque apareció y funcionó (o la aplicación). en el mejor de los casos, una sensación cálida y difusa, pero no una prueba.