Bagikan melalui


Panduan implementasi firmware Component Firmware Update (CFU)

Component Firmware Update (CFU) adalah protokol dan proses untuk mengirimkan gambar firmware baru yang akan diinstal pada perangkat target.

Catatan

CFU tersedia di Windows 10, versi 2004 (Windows 10 Pembaruan Mei 2020) dan versi yang lebih baru.

Pengiriman CFU ke firmware residen adalah pasangan file, satu file adalah bagian penawaran, file lainnya adalah bagian konten. Setiap pengiriman CFU (setiap penawaran dan pasangan konten) harus dibuat secara off-line sebelum pengiriman dikirim ke firmware yang mengimplementasikan proses CFU.

Dalam sampel kode sumber Firmware di repositori CFU di GitHub, kode umum agnostik implementasi umum untuk CFU terkandung dalam ComponentFwUpdate.c. Semua file lain adalah file pembantu yang dapat diperbarui atau dimodifikasi ke implementasi unik pengembang.

Konten

Bagian penawaran dan konten

Penawaran dan konten membentuk sepasang file dalam skema CFU.

Bagian penawaran hanyalah file panjang 16 byte yang memetakan ke struktur FWUPDATE_OFFER_COMMAND yang diuraikan di bawah ini.

Bagian konten, firmware aktual yang akan diperbarui dalam format yang ditentukan oleh pengembang pengguna akhir. Kode sampel CFU yang disediakan menggunakan file SREC untuk konten firmware.

Penawarannya adalah urutan 16 byte. Struktur penawaran ini dimasukkan ke dalam file penawaran. Ini pada dasarnya adalah data biner, bukan teks, karena penawaran berisi bidang bit dari arti tertentu.

Penawaran yang diwakili dalam peta file ke struktur C ini:

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;

Dari alamat rendah ke alamat tinggi, byte pertama dari penawaran adalah nomor segmen.

  <------- 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  |
+================================-=============================================+

Dari alamat tinggi ke alamat rendah:

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
---------------------------------------------------------

Detail daftar penawaran

ID Produk. Nilai ID produk unik untuk gambar CFU ini dapat diterapkan ke bidang ini.

UINT16 productID;  

Tonggak pencapaian firmware yang diwakili konten penawaran. Milestones bisa menjadi versi build HW yang berbeda, misalnya, build EV1, build EV2, dan sebagainya. Definisi milestone dan penetapan nilai diserahkan kepada pengembang.

UINT8 milestone : 3;

Jika firmware ditujukan untuk bank tertentu - bidang 2-bit mendukung empat bank. Penggunaan register bank disertakan dalam format penawaran karena ada instans di mana perangkat target menggunakan wilayah firmware banked.

Jika itu masalahnya, dan penawaran dimaksudkan untuk memperbarui bank yang digunakan, firmware yang menerapkan CFU pada target dapat menolak penawaran. Jika tidak, firmware pada target yang menerapkan CFU dapat mengambil tindakan lain sesuai jaminan.

Jika perbankan gambar firmware TIDAK dalam desain firmware pengguna akhir, maka wajar untuk mengabaikan bidang ini (diatur ke nilai apa pun yang nyaman, tetapi nilai di bidang bank bersifat opsional dan tergantung pada cara firmware target menerapkan CFU).

UINT8 bank : 2;

Versi protokol protokol CFU yang digunakan dalam 4 bit.

UINT8 protocolRevision : 4;

Bitmask yang sesuai dengan semua HW unik yang dapat dioperasikan oleh gambar firmware ini. Misalnya, penawaran dapat menandakan dapat berjalan pada puncak HW tetapi tidak di verY HW. Definisi bit dan penetapan nilai diserahkan kepada pengembang.

UINT32 hwVariantMask;

Versi firmware yang ditawarkan.

UINT32 version;

Token byte untuk mengidentifikasi perangkat lunak khusus pengguna yang membuat penawaran. Ini dimaksudkan untuk membedakan antara driver dan alat yang mungkin mencoba memperbarui firmware yang berjalan sama. Misalnya, driver pembaruan CFU dapat ditetapkan token 0xA dan alat updater pengembangan dapat ditetapkan 0xB. Sekarang firmware yang sedang berjalan dapat secara selektif memilih untuk menerima atau mengabaikan perintah berdasarkan proses mana yang mencoba memperbaruinya.

UINT8 token;

Komponen dalam perangkat untuk menerapkan pembaruan firmware.

UINT8 componentId;

menawarkan bendera interpretasi: Jika kita ingin firmware in situ mengabaikan ketidakcocokan versi (lebih lama di atas yang lebih baru) maka atur bit untuk memaksa Abaikan Versi.

UINT8 forceIgnoreVersion: 1;

Memaksa reset segera dinyatakan dengan satu bit. Jika bit tersebut ditegaskan, perangkat lunak host mengharapkan firmware in situ menyebabkan perangkat melakukan reset. Tindakan reset bersifat spesifik untuk platform. Firmware perangkat dapat memilih untuk mengambil tindakan yang menukar bank untuk membuat firmware yang baru diperbarui aktif di firmware situ. Atau tidak. Ini diserahkan pada implementasi firmware. Harapannya biasanya adalah bahwa jika reset langsung paksa ditegaskan, bahwa perangkat akan melakukan apa pun yang diperlukan untuk menyebabkan firmware membuat bank baru diperbarui menjadi firmware aktif yang berjalan pada perangkat target.

UINT8 forceImmediateReset : 1;

Jika bagian konten dari penawaran dan pasangan konten melibatkan beberapa bagian konten.

UINT8 segmentNumber;

Memproses penawaran

ProcessCFWUOffer API menerima dua argumen:

void ProcessCFWUOffer(FWUPDATE_OFFER_COMMAND* pCommand,
                     FWUPDATE_OFFER_RESPONSE* pResponse)

Dalam kasus penggunaan ini, asumsikan perangkat lunak pengguna mengirim byte data ke firmware yang sedang berjalan, maka pesan pertama adalah pesan penawaran.

Pesan penawaran adalah pesan 16 byte yang dijelaskan di atas (struktur FWUPDATE_OFFER_COMMAND).

Pesan penawaran tersebut adalah data yang digunakan oleh firmware yang sedang berjalan untuk mendisposisikan penawaran.

Selama disposisi penawaran, firmware yang berjalan memberi tahu pengirim dengan mengisi bidang dalam FWUPDATE_OFFER_RESPONSE struktur.

Menginterpretasikan penawaran

Firmware yang berjalan harus melacak statusnya dalam proses CFU. Mungkin siap/menunggu untuk menerima penawaran, di tengah transaksi CFU, atau menunggu untuk menukar bank antara firmware aktif/tidak aktif.

Jika firmware yang sedang berjalan berada di tengah transaksi CFU - jangan terima/proses penawaran ini dan beri tahu host yang sesuai.

   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;
   }

Bidang ID komponen penawaran dapat digunakan untuk memberi sinyal firmware yang sedang berjalan bahwa tindakan khusus diminta dari firmware yang sedang berjalan. Dalam contoh kode CFU, perintah penawaran khusus digunakan oleh host untuk mengambil status mesin CFU - apakah perangkat lunak yang sedang berjalan mampu dan siap menerima Penawaran 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;
       }
   }

Akhirnya, pemeriksaan dilakukan jika ada pertukaran bank tertunda. Pertukaran bank mengacu pada firmware yang mempertahankan informasi apakah masih dalam proses beralih dari aplikasi aktif yang sedang berjalan ke gambar yang baru diunduh.

Bagaimana dan di mana pengalihan bank dilakukan adalah implementasi tugas khusus untuk firmware yang disematkan. Protokol dan proses CFU memungkinkan informasi dipertukarkan antara aplikasi pengguna jarak jauh yang melakukan CFU dan firmware in situ yang sedang berjalan.

   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;
   }

Akhirnya, jika status firmware yang berjalan tidak sibuk, dan componentId bukan perintah khusus dan tidak ada pertukaran bank yang tertunda - MAKA kita dapat memproses penawaran ini.

Memproses penawaran melibatkan, tetapi tidak terbatas pada, empat langkah yang diuraikan di bawah ini:

Langkah 1 - Periksa bank

Periksa bank aplikasi yang sedang berjalan ke bank dalam penawaran. Apakah mereka sama atau berbeda?

Jika sama, maka tolak penawaran (kami tidak ingin menimpa gambar yang sedang berjalan/aktif).

Lain lanjutkan.

Langkah 2 - Periksa hwVariantMask

Firmware yang hwVariantMask sedang berjalan memeriksa dalam penawaran terhadap HW yang dijalankannya. Ini memungkinkan firmware yang disematkan untuk menolak penawaran jika penawaran tidak valid untuk target. (mis. jika firmware yang berjalan berada di build HW lama dan firmware baru yang ditawarkan dimaksudkan untuk build HW yang lebih baru - maka firmware yang berjalan harus menolak penawaran ini)

Jika tidak valid, maka tolak penawaran.

Lain lanjutkan.

Langkah 3 - Periksa versi firmware

Periksa apakah versi konten firmware yang ditawarkan memiliki versi yang lebih lama atau lebih baru dari firmware aplikasi saat ini.

Ini diserahkan ke implementasi pengguna untuk memutuskan cara memeriksa firmware mana yang lebih besar dari yang lain dan jika untuk mengizinkan bidang 'forceIgnoreVersion' dalam penawaran untuk digunakan. Pengembangan firmware yang khas akan memungkinkan bidang 'forceIgnoreVersion' digunakan selama pengembangan produk dan dalam versi debug firmware tetapi tidak diizinkan (tidak memungkinkan firmware yang lebih lama diperbarui di atas firmware baru) dalam firmware produk/rilis.

Jika pemeriksaan ini gagal, maka tolak penawaran.

Lain lanjutkan.

Langkah 4 - Terima penawaran

Penawarannya bagus. Terima penawaran dengan respons yang disesuaikan untuk cara pesan dan status dikembalikan oleh firmware ke aplikasi pengguna jarak jauh. Yang disebut "respons" adalah data (struktur data yang dikemas seperti yang ditunjukkan dalam file header demonstrasi) dan data ini ditulis ke aplikasi pengguna dengan cara yang sesuai untuk perangkat.

Memproses konten

Pemrosesan konten biasanya merupakan proses multistep. Beberapa langkah mengacu pada kemampuan firmware untuk menerima gambar firmware di beberapa bagian, juga dikenal sebagai "blok" data. Tidak selalu layak untuk mengirim seluruh gambar sekaligus ke firmware yang disematkan, sehingga realistis untuk mengharapkan implementasi protokol dan proses CFU untuk menerima konten dalam potongan-potongan kecil.

Diskusi ini menggunakan asumsi saat menjelaskan proses konten CFU.

Mesin status pemrosesan konten melibatkan tiga status.

  1. Status pemrosesan blok pertama.

  2. Status pemrosesan blok terakhir.

  3. Status pemrosesan blok apa pun di antara pertama dan terakhir.

Struktur perintah konten

Seperti penawaran, konten memiliki struktur dengan bidang yang digunakan oleh algoritma CFU dalam demonstrasi.

typedef struct
{
   UINT8 flags;
   UINT8 length;
   UINT16 sequenceNumber;
   UINT32 address;
   UINT8 pData[MAX_UINT8];
} FWUPDATE_CONTENT_COMMAND;

Struktur perintah konten lebih sederhana daripada struktur penawaran. Konten didefinisikan sebagai urutan byte yang akan ditulis ke dalam memori. Awal konten adalah bidang struktur ini:

  1. UINT8 flags Menunjukkan apakah konten "blok" adalah yang pertama, terakhir, atau lainnya.

  2. UINT8 length Menandai panjang pData bidang. Dalam kode demonstrasi untuk CFU, batas ukurannya pData adalah 255 byte. Implementasi lain dapat bervariasi ukuran maksimum "blok".

  3. UINT16 sequenceNumber Menandai penghitung indeks dari blok mana yang sedang dikirimkan sebagai konten.

  4. UINT32 address Offset alamat blok. Dalam demonstrasi CFU rilis ini, implementasi memiliki informasi yang telah ditentukan sebelumnya tentang alamat fisik setiap wilayah Aplikasi. Misalnya, dua implementasi firmware bank mungkin memiliki App1 dimulai di alamat 0x9000 dan App2 dimulai di alamat 0xA0000. Jadi, tergantung pada bagaimana gambar firmware disiapkan (S-Records) alamat di SREC mungkin berupa alamat fisik atau offset. Bagaimanapun, perlu ada pemahaman bersama antara persiapan konten dan rutinitas spesifik implementasi dari pemrosesan konten CFU untuk menentukan alamat fisik sebenarnya tempat menulis blok dalam memori. Diserahkan kepada pengembang firmware untuk mengadopsi praktik terbaik dan melakukan pemeriksaan untuk rentang alamat yang valid untuk setiap blog konten. Misalnya, kode CFU menunjukkan pemeriksaan yang dilakukan jika mungkin App1 (dimaksudkan untuk 0x9000) memiliki alamat yang tumpang tindih ke App2, dan sebagainya.

  5. UINT8 pData[MAX_UINT8] - Ini adalah byte mentah dari blok gambar firmware. Perawatan diambil dalam aplikasi pengguna untuk hanya memasukkan length byte ke dalam aliran byte lengkap blok konten.

Tidak ada bidang bit yang digunakan dalam struktur konten sesuai demonstrasi CFU dari kode yang disediakan.

Blok pertama

Blok pertama memulai pengunduhan konten firmware. Firmware yang berjalan mencoba menulis blok ke dalam memori non-volatil. Tentu saja konten "blok" berisi informasi tentang di mana dalam memori blok harus ditulis, berapa banyak data yang harus ditulis dan bidang lainnya.

Setiap perangkat target componentID berbeda dan ada beberapa metode untuk mempertahankan data ke dalam memori. Misalnya, satu componentId dapat memerlukan penulisan ke lampu kilat internal, componentId lain dapat menulis ke flash SPI eksternal atau yang lain dapat menggunakan protokol I2C IC lain untuk memperbarui gambarnya. Demonstrasi yang disertakan dengan dokumen ini menyoroti penggunaan fungsi yang disebut ICompFwUpdateBspWrite yang harus diterapkan setiap firmware unik dengan pengetahuan tentang fungsi I/O memori non-volatil yang mendasar dari target yang dirancang untuknya.

Blok lain kecuali yang pertama atau terakhir

Proses menerima blok baru berlanjut ketika aplikasi pengguna mengirimkan blok lain, sekali lagi dengan meta data dalam pesan untuk alamat tempat blok harus ditulis, berapa banyak byte yang terkandung, dan bidang lainnya.

firmware in situ akan memperlakukan ini seperti skenario blok pertama.

Namun, perlu dicatat bahwa setiap saat sistem gagal menangkap dan mempertahankan blok ke dalam memori, terserah firmware situ untuk merespons dengan kode kegagalan.

Blok terakhir

Blok terakhir menyajikan tantangan hanya jika firmware in situ perlu melakukan tugas untuk memvalidasi gambar yang hanya ditulis ke memori.

Pertama, blok terakhir ditulis ke memori.

Kemudian, minimal, pemeriksaan CRC harus dilakukan antara data yang sudah ditulis ke memori (dari blok pertama hingga terakhir) dibandingkan dengan bidang CRC di blok terakhir. Diserahkan ke setiap firmware implementasi untuk mengetahui cara memperoleh CRC untuk gambar yang diunduh.

Perlu diingat bahwa eksekusi pemeriksaan CRC memang membutuhkan waktu. Tidak seperti alur normal eksekusi CFU untuk pengajuan penawaran dan blok. Pengajuan blok terakhir, jika menyertakan pemeriksaan CRC, akan memiliki keterlambatan tertentu yang terlibat hanya untuk fakta bahwa pemeriksaan CRC berpotensi memeriksa wilayah memori yang besar. Tergantung pada perangkat target dan faktor lain, ini mungkin tidak menjadi perhatian.

Penting

Pemeriksaan CRC gambar masuk bersifat opsional dan dapat dikomentari. Namun, praktik terbaik harus diberlakukan untuk setidaknya mengadopsi pemeriksaan ini. Sangat disarankan bahwa pada saat ini dalam proses CFU, tindakan lain diambil untuk memastikan integritas gambar yang diunduh. Beberapa tindakan ini dapat mencakup verifikasi bagian gambar yang 'ditandatangani' dan/atau memeriksa rantai sertifikat kepercayaan atau pendekatan praktik terbaik lainnya untuk memastikan gambar firmware yang aman. Ini diserahkan kepada pengembang firmware.

Bersihkan setelah blok terakhir

Sekarang setelah blok terakhir ditulis, dan pemeriksaan CRC selesai, firmware dapat merespons dengan kegagalan jika ada bagian dari validasi yang gagal.

Jika tidak, harapannya adalah bahwa proses CFU di firmware akan merespons dengan status berhasil.

Reset paksa diperiksa

Bendera reset paksa dalam penawaran digunakan untuk menentukan apakah MCU target harus menjalani reset (reset yang ditentukan pengguna).

Biasanya ketika reset dipaksa, niatnya adalah untuk menyebabkan MCU melakukan reset untuk menyebabkan bank Aplikasi beralih. Memperbarui variabel persisten untuk menunjukkan gambar firmware apa yang akan di-boot pada reset diserahkan kepada pengembang firmware.