Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Component Firmware Update (CFU) ist ein Protokoll und ein Prozess zum Übermitteln neuer Firmwareimages, die auf dem Zielgerät installiert werden sollen.
Hinweis
CFU ist in Windows 10, Version 2004 (Windows 10 Mai 2020 Update) und höheren Versionen verfügbar.
CFU-Übermittlungen an die residente Firmware sind Dateipaare, eine Datei ist der Angebotsteil, die andere Datei ist der Inhaltsteil. Jede CFU-Übermittlung (jedes Angebot und jedes Inhaltspaar) muss off-line erstellt werden, bevor die Übermittlung an die Firmware gesendet wird, die den CFU-Prozess implementiert.
Im Beispiel-Firmware-Quellcode im CFU-Repository auf GitHub ist der allgemeine, unabhängig von der Implementierung gehaltene Code für CFU in ComponentFwUpdate.c enthalten. Alle anderen Dateien sind Hilfsdateien, die auf die eindeutige Implementierung des Entwicklers aktualisiert oder geändert werden können.
Inhalt
- Die Angebots- und Inhaltsteile
Die Angebots- und Inhaltsteile
Das Angebot und der Inhalt bilden ein Paar Dateien im CFU-Schema.
Das Angebotsteil ist einfach eine 16-Byte-lange Datei, die der unten beschriebenen FWUPDATE_OFFER_COMMAND Struktur zugeordnet ist.
Der Inhaltsteil, die tatsächliche Firmware, die aktualisiert werden soll, befindet sich im Format, das vom Endbenutzerentwickler vorgegeben wird. Der bereitgestellte CFU-Beispielcode verwendet SREC-Dateien für Firmwareinhalte.
Das Angebot ist eine 16-Byte-Sequenz. Diese Angebotsstruktur wird in die Angebotsdatei eingefügt. Es handelt sich im Wesentlichen um binäre Daten, nicht um Text, da das Angebot Bitfelder mit spezifischer Bedeutung enthält.
Das Angebot, das in der Datei dargestellt wird, ist dieser C-Struktur zugeordnet:
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;
Von niedriger Adresse bis zu hoher Adresse ist das erste Byte des Angebots eine Segmentnummer.
<------- 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 |
+================================-=============================================+
Von hoher Adresse bis hin zu niedriger Adresse:
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
---------------------------------------------------------
Details des Angebotsregisters
Die Produkt-ID. Auf dieses Feld kann ein eindeutiger Produkt-ID-Wert für dieses CFU-Bild angewendet werden.
UINT16 productID;
Der Meilenstein der Firmware, den der Inhalt des Angebots darstellt. Meilensteine können verschiedene Versionen des HW-Builds sein, z. B. EV1-Build, EV2-Build usw. Meilensteindefinition und Wertzuweisung bleiben dem Entwickler überlassen.
UINT8 milestone : 3;
Wenn die Firmware für eine bestimmte Bank vorgesehen ist - unterstützt das 2-Bit-Feld vier Banken. Die Verwendung eines Bankregisters ist im Format des Angebots enthalten, da es Fälle gibt, in denen die Zielgeräte bankierte Firmwareregionen verwenden.
Wenn dies der Fall wäre, und das Angebot dazu gedacht war, eine verwendete Bank zu aktualisieren, kann die Firmware, die CFU auf dem Zielgerät ausführt, das Angebot ablehnen. Andernfalls kann die Firmware des Ziels, das CFU implementiert, andere geeignete Maßnahmen ergreifen.
Falls das Banking von Firmware-Abbildern nicht im Design der Endbenutzerfirmware vorgesehen ist, ist es vernünftig, dieses Feld zu ignorieren (auf beliebige Werte einzustellen, die praktisch sind; jedoch ist der Wert im Bankfeld optional und hängt von der Art und Weise ab, wie die Zielfirmware CFU implementiert).
UINT8 bank : 2;
Die verwendete Protokollversion des CFU-Protokolls ist in 4 Bits.
UINT8 protocolRevision : 4;
Die Bitmaske, die allen einzigartigen Hardwarekomponenten entspricht, auf denen dieses Firmware-Image ausgeführt werden kann. Beispielsweise kann das Angebot bedeuten, dass es auf VerX von HW, aber nicht auf VerY von HW ausgeführt werden kann. Bitdefinition und Wertzuweisung bleiben dem Entwickler überlassen.
UINT32 hwVariantMask;
Die Version der angebotenen Firmware.
UINT32 version;
Ein Bytetoken, um die benutzerspezifische Software zu identifizieren, die das Angebot macht. Dies soll zwischen Treibern und Tools unterscheiden, die beide versuchen, dieselbe ausgeführte Firmware zu aktualisieren. Beispielsweise kann einem CFU-Updatetreiber token 0xA zugewiesen werden, und ein Entwicklungsupdater-Tool kann 0xB zugewiesen werden. Jetzt kann die ausgeführte Firmware selektiv festlegen, dass Befehle akzeptiert oder ignoriert werden, basierend auf dem Prozess, der versucht, sie zu aktualisieren.
UINT8 token;
Die Komponente auf dem Gerät, um das Firmwareupdate anzuwenden.
UINT8 componentId;
Bieten Sie Interpretationsflags an: Wenn die in situ-Firmware den Versionskonflikt ignorieren soll (ältere Version über der neueren), setzen Sie das Bit, um 'Version ignorieren' zu erzwingen.
UINT8 forceIgnoreVersion: 1;
Das Erzwingen des sofortigen Zurücksetzens wird mit einem Bit bestätigt. Wenn dieses Bit gesetzt ist, erwartet die Hostsoftware, dass die In-situ-Firmware das Gerät zu einem Neustart veranlasst. Die Aktionen des Zurücksetzens sind plattformspezifisch. Die Firmware des Geräts kann Maßnahmen ergreifen, die Speicherbereiche austauschen, um die frisch aktualisierte Firmware zur vor Ort aktiven Firmware zu machen. Oder nicht. Dies bleibt bis zur Implementierung der Firmware. Die Erwartung besteht in der Regel darin, dass, wenn die sofortige Zurücksetzung erzwungen wird, das Gerät alles Notwendige unternimmt, damit die Firmware die neue Bank aktualisiert, sodass diese zur aktiven Firmware wird, die auf dem Zielgerät ausgeführt wird.
UINT8 forceImmediateReset : 1;
Falls der Inhaltsteil des Angebots und des Inhaltspaars mehrere Teile von Inhalten umfasst.
UINT8 segmentNumber;
Angebote zur Verarbeitung
Die ProcessCFWUOffer-API akzeptiert zwei Argumente:
void ProcessCFWUOffer(FWUPDATE_OFFER_COMMAND* pCommand,
FWUPDATE_OFFER_RESPONSE* pResponse)
In diesem Anwendungsfall wird davon ausgegangen, dass die Benutzersoftware Datenbytes an die ausgeführte Firmware sendet, und dann ist die erste Nachricht die Angebotsnachricht.
Die Angebotsnachricht ist eine oben beschriebene 16-Byte-Nachricht (die FWUPDATE_OFFER_COMMAND Struktur).
Diese Angebotsnachricht ist die Daten, die von der ausgeführten Firmware verwendet werden, um das Angebot zu bearbeiten.
Während der Bereitstellung des Angebots benachrichtigt die laufende Firmware den Absender, indem sie Felder in der FWUPDATE_OFFER_RESPONSE Struktur ausfüllt.
Interpretieren des Angebots
Die laufende Firmware sollte ihren Zustand im CFU-Prozess nachverfolgen. Es kann bereit sein oder darauf warten, ein Angebot anzunehmen, sich in der Mitte einer CFU-Transaktion befinden oder darauf warten, Banken zwischen aktiver und inaktiver Firmware zu tauschen.
Wenn sich die ausgeführte Firmware in der Mitte einer CFU-Transaktion befindet , akzeptieren/verarbeiten Sie dieses Angebot nicht, und benachrichtigen Sie den Host entsprechend.
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;
}
Das Komponenten-ID-Feld des Angebots kann verwendet werden, um die ausgeführte Firmware zu signalisieren, dass eine spezielle Aktion von der ausgeführten Firmware angefordert wird. Im CFU-Beispielcode wird ein spezieller Befehlsaufruf vom Host verwendet, um den Status der CFU-Engine abzurufen – ob die ausgeführte Software fähig und bereit ist, CFU-Angebote zu akzeptieren.
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;
}
}
Schließlich wird eine Prüfung durchgeführt, ob ein Banktausch aussteht. Der Begriff "Banktausch" bezieht sich auf die Firmware, die Informationen darüber speichert, ob sie sich noch im Umschaltprozess von der aktuell ausgeführten, aktiven Anwendung zum neu heruntergeladenen Abbild befindet.
Wie und wo bankwechsel ausgeführt wird, ist eine implementierungsspezifische Aufgabe für die eingebettete Firmware. Das CFU-Protokoll und der Prozess ermöglichen den Austausch von Informationen zwischen der Remotebenutzeranwendung, die die CFU durchführt, und der in situ ausgeführten Firmware.
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;
}
Wenn der Zustand der laufenden Firmware nicht ausgelastet ist, die componentId kein spezieller Befehl ist und kein Banktausch aussteht, dann können wir dieses Angebot verarbeiten.
Die Verarbeitung eines Angebots umfasst, aber nicht beschränkt auf die folgenden vier Schritte:
Schritt 1 : Bank überprüfen
Überprüfen Sie die Bank des laufenden Antrags auf die Bank im Angebot. Sind sie gleich oder anders?
Wenn es dasselbe ist, lehnen Sie das Angebot ab (wir möchten das laufende/aktive Abbild nicht überschreiben).
Andernfalls fahren Sie fort.
Schritt 2 – hwVariantMask überprüfen
Die ausgeführte Firmware überprüft das hwVariantMask im Angebot mit der Hardware, auf der es läuft. Dadurch kann die eingebettete Firmware ein Angebot ablehnen, wenn das Angebot für das Ziel ungültig ist. (z. B. wenn sich die ausgeführte Firmware auf einem alten HW-Build befindet und die neue angebotene Firmware für einen neueren, HW-Build vorgesehen ist, sollte die ausgeführte Firmware dieses Angebot ablehnen)
Wenn dies ungültig ist, lehnen Sie das Angebot ab.
Andernfalls fahren Sie fort.
Schritt 3 : Überprüfen der Firmwareversion
Überprüfen Sie, ob die version des angebotenen Firmwareinhalts eine ältere oder neuere Version als die aktuelle Anwendungsfirmware aufweist.
Es liegt bei der Implementierung des Benutzers, zu entscheiden, wie überprüft wird, welche Firmware-Version größer ist als eine andere und ob das Feld "forceIgnoreVersion" im Update-Angebot verwendet werden soll. Die typische Firmwareentwicklung würde es ermöglichen, dass das Feld "forceIgnoreVersion" während der Produktentwicklung und in Debugversionen der Firmware verwendet wird, aber nicht zulässig ist (nicht zulassen, dass ältere Firmware über neue Firmware aktualisiert werden kann) in Produkt-/Release-Firmware.
Wenn diese Überprüfung fehlgeschlagen ist, lehnen Sie das Angebot ab.
Andernfalls fahren Sie fort.
Schritt 4 – Angebot annehmen
Das Angebot ist gut. Akzeptieren Sie das Angebot mit einer Antwort, die auf die Art und Weise angepasst ist, wie Nachrichten und Status von der Firmware an die Remotebenutzeranwendung zurückgegeben werden. Die sogenannte "Response" ist Daten (eine gepackte Datenstruktur, wie in den Demonstrationsheaderdateien dargestellt), und diese Daten werden mit geeigneten Methoden des Geräts an die Benutzeranwendung übertragen.
Verarbeiten des Inhalts
Die Verarbeitung des Inhalts ist in der Regel ein mehrstufiger Prozess. Die mehreren Schritte beziehen sich auf die Fähigkeit der Firmware, das Firmwareimage in Teilen zu akzeptieren, auch als "Blöcke" von Daten bezeichnet. Es ist nicht immer möglich, das gesamte Bild auf einmal an die eingebettete Firmware zu senden; daher ist es sinnvoll, die Implementierung des CFU-Protokolls und Prozesses so zu gestalten, dass Inhalte in kleinen Teilen akzeptiert werden.
Diese Diskussion basiert auf der Annahme, wenn der Prozess der CFU-Inhalte beschrieben wird.
Der Zustandsautomat der Inhaltsverarbeitung umfasst drei Zustände.
Der Status der Verarbeitung des ersten Blocks.
Der Status der Verarbeitung des letzten Blocks.
Der Status der Verarbeitung eines Blocks zwischen dem ersten und dem letzten.
Die Struktur des Inhaltsbefehls
Wie das Angebot verfügt der Inhalt über eine Struktur mit Feldern, die von den CFU-Algorithmen in der Demonstration verwendet werden.
typedef struct
{
UINT8 flags;
UINT8 length;
UINT16 sequenceNumber;
UINT32 address;
UINT8 pData[MAX_UINT8];
} FWUPDATE_CONTENT_COMMAND;
Die Struktur des Inhaltsbefehls ist einfacher als die Angebotsstruktur. Der Inhalt wird als Eine Abfolge von Bytes definiert, die in den Arbeitsspeicher geschrieben werden sollen. Die Präambel des Inhalts besteht aus den Feldern dieser Struktur.
UINT8 flagsGibt an, ob der Inhalt "Block" der erste, letzte oder andere ist.UINT8 lengthMarkiert die Länge despDataFelds. Im Democode für CFU beträgt der Grenzwert für die Größe derpData255 Bytes. Andere Implementierungen können die maximale Größe des "Blocks" variieren.UINT16 sequenceNumberMarkiert den Indexzähler des Blocks, der als Inhalt übermittelt wird.UINT32 addressDer Adressoffset des Blocks. In der Demonstration der CFU dieser Version enthält die Implementierung vordefinierte Informationen zur physischen Adresse jeder App-Region. Bei einer Implementierung der Firmware für zwei Bänke kann z. B. "App1" an der Adresse0x9000beginnen und "App2" an der Adresse0xA0000beginnen. Je nachdem, wie das Firmwareimage vorbereitet wurde (S-Records), kann die Adresse im SREC entweder die physische Adresse oder ein Offset sein. In jedem Fall muss ein gemeinsames Verständnis zwischen der Vorbereitung des Inhalts und den Implementierungsspezifischen Routinen der CFU-Inhaltsverarbeitung vorhanden sein, um die wahre physische Adresse zu bestimmen, an der der Block im Speicher geschrieben werden soll. Es bleibt dem Firmwareentwickler überlassen, bewährte Methoden zu übernehmen und nach gültigen Adressbereichen für jeden Inhaltsblog zu suchen. Beispielsweise veranschaulicht der CFU-Code eine Überprüfung, die durchgeführt wird, um zu überprüfen, ob möglicherweise App1 (vorgesehen für0x9000) Adressen enthält, die mit App2 überlappen, und so weiter.UINT8 pData[MAX_UINT8]- Dies sind die unformatierten Bytes des Firmwareimageblocks. In der Benutzeranwendung wird darauf geachtet, dass nurlengthBytes in den vollständigen Bytestrom des Inhaltsblocks eingefügt werden.
In der Inhaltsstruktur werden gemäß der CFU-Demonstration aus dem bereitgestellten Code keine Bitfelder verwendet.
Der erste Block
Der erste Block startet den Download der Firmwareinhalte. Die ausgeführte Firmware versucht, den Block in nicht veränderlichen Speicher zu schreiben. Der Inhalt "Block" enthält natürlich Informationen darüber, wo der Block im Arbeitsspeicher geschrieben werden soll, wie viel Daten geschrieben werden sollen, und andere Felder.
Jedes ComponentID-Zielgerät ist unterschiedlich, und es gibt mehrere Methoden, um die Daten im Arbeitsspeicher zu speichern. Eine ComponentId könnte z. B. das Schreiben in internen Flash erfordern, eine andere ComponentId könnte in einen externen SPI-Flash schreiben, oder eine weitere könnte das I2C-Protokoll eines anderen ICs verwenden, um ihr Image zu aktualisieren. Die in diesem Dokument enthaltene Demonstration hebt die Verwendung einer Funktion namens ICompFwUpdateBspWrite hervor, die von jeder eindeutigen Firmware implementiert werden muss. Diese Implementierung erfordert Kenntnisse der zugrunde liegenden nichtflüchtigen Speicher-E/A-Funktionen des Ziels, für das sie entwickelt wurde.
Jeder andere Block mit Ausnahme der ersten oder letzten
Der Vorgang zum Akzeptieren neuer Blöcke wird fortgesetzt, wenn die Benutzeranwendung einen weiteren Block liefert; in der Nachricht befinden sich die Metadaten für die Adresse, an der der Block geschrieben werden soll, die Anzahl der enthaltenen Bytes und andere Felder.
Die In-Situ-Firmware würde dies genauso wie ein erstes Blockszenario behandeln.
Beachten Sie jedoch, dass jedes Mal, wenn das System den Block nicht erfasst und im Speicher speichert, die in situ Firmware darauf mit einem Fehlercode reagieren muss.
Der letzte Block
Der letzte Block stellt eine Herausforderung nur dar, wenn die In-Situ-Firmware Aufgaben ausführen muss, um das soeben in den Arbeitsspeicher geschriebene Bild zu überprüfen.
Zuerst wird der letzte Block in den Arbeitsspeicher geschrieben.
Anschließend sollte mindestens eine CRC-Prüfung zwischen den bereits in den Speicher geschriebenen Daten (vom ersten bis zum letzten Block) und dem CRC-Feld im letzten Block erfolgen. Es obliegt jeder Implementierungsfirmware, zu bestimmen, wie das CRC für das heruntergeladene Image zu erfassen ist.
Beachten Sie, dass die Ausführung der CRC-Prüfung Zeit in Anspruch nimmt. Im Gegensatz zum normalen Ablauf der CFU-Ausführung für die Angebotserstellung und das Blockieren von Übermittlungen. Die letzte Blockübermittlung wird, falls sie eine CRC-Prüfung umfasst, eine gewisse Verzögerung aufweisen, da die CRC-Prüfung potenziell eine große Speicherregion untersucht. Je nach Zielgerät und anderen Faktoren ist dies möglicherweise kein Problem.
Von Bedeutung
Die CRC-Prüfung des eingehenden Bilds ist optional und kann auskommentiert werden. Es sollten jedoch bewährte Methoden angewendet werden, um diese Prüfung zumindest zu übernehmen. Es wird dringend empfohlen, dass an diesem Punkt im CFU-Prozess weitere Maßnahmen ergriffen werden, um die Integrität des heruntergeladenen Bilds sicherzustellen. Einige dieser Aktionen könnten das Überprüfen eines "signierten" Teils des Images und/oder die Überprüfung von Zertifikatketten mit Vertrauen oder andere bewährte Methoden umfassen, um ein sicheres Firmwareimage sicherzustellen. Dies bleibt dem Firmwareentwickler überlassen.
Bereinigen nach dem letzten Block
Nachdem der letzte Block geschrieben wurde und die CRC-Prüfung abgeschlossen ist, reagiert die Firmware möglicherweise mit einem Fehler, wenn ein Teil der Überprüfung fehlgeschlagen ist.
Andernfalls wird erwartet, dass der CFU-Prozess in der Firmware mit einem erfolgreichen Status reagiert.
Erzwungenes Zurücksetzen überprüft
Die Kennzeichnung zum erzwungenen Zurücksetzen im Angebot wird verwendet, um zu bestimmen, ob die MCU des Ziels einer Zurücksetzung unterzogen wird (benutzerdefiniertes Zurücksetzen).
In der Regel wird durch ein erzwungenes Zurücksetzen beabsichtigt, dass die MCU einen Reset durchführt, um die App-Bank zu wechseln. Das Aktualisieren persistenter Variablen, um zu kennzeichnen, in welchem Firmwareimage beim Zurücksetzen gestartet werden soll, bleibt dem Firmwareentwickler überlassen.