目錄
概述
1 MCUboot的功能
1.1 代碼包結構
1.2 限制
2 MCUboot Image
2.1 Image格式
2.2 Flash Map
2.3 Image 槽
2.4 使用scratch交換
?2.5 Image 尾部數據結構
3 交換區
3.1 單交換區
?3.2 Multiple Image boot?
3.3 Image交換
4??交換狀態(swap status)
?5 復位覆蓋
概述
本文主要介紹MCUboot的實現原理和Image的結構,主要包括MCUboot的Image的格式,交換區,Resetrecovery等概念,還介紹了使用Image進行代碼更新的步驟。
1 MCUboot的功能
1.1 代碼包結構
MCUboot包含兩個代碼包:
1)The bootutil library (boot/bootutil)
2)The boot application (each port has its own at boot/)
bootutil 庫執行了引導加載程序的大部分功能。特別缺少的是實際跳轉到主映像的最后一步。這最后一步則由引導應用程序來實現。以這種方式分離引導加載程序的功能是為了能夠對引導加載程序進行單元測試。庫可以進行單元測試,但應用程序不行。因此,只要有可能,功能就會委托給 bootutil 庫。?
1.2 限制
當前,引導加載程序僅支持具有以下特征的映像:
1)?Built to run from flash.
2)? ?Built to run from a fixed location (i.e., not position-independent).
2 MCUboot Image
2.1 Image格式
以下定義描述image格式:
#define IMAGE_MAGIC 0x96f3b83d#define IMAGE_HEADER_SIZE 32struct image_version {uint8_t iv_major;uint8_t iv_minor;uint16_t iv_revision;uint32_t iv_build_num;
};/** Image header. All fields are in little endian byte order. */
struct image_header {uint32_t ih_magic;uint32_t ih_load_addr;uint16_t ih_hdr_size; /* Size of image header (bytes). */uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */uint32_t ih_img_size; /* Does not include header. */uint32_t ih_flags; /* IMAGE_F_[...]. */struct image_version ih_ver;uint32_t _pad1;
};#define IMAGE_TLV_INFO_MAGIC 0x6907
#define IMAGE_TLV_PROT_INFO_MAGIC 0x6908/** Image TLV header. All fields in little endian. */
struct image_tlv_info {uint16_t it_magic;uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */
};/** Image trailer TLV format. All fields in little endian. */
struct image_tlv {uint8_t it_type; /* IMAGE_TLV_[...]. */uint8_t _pad;uint16_t it_len; /* Data length (not including TLV header). */
};/** Image header flags.*/
#define IMAGE_F_PIC 0x00000001 /* Not supported. */
#define IMAGE_F_ENCRYPTED_AES128 0x00000004 /* Encrypted using AES128. */
#define IMAGE_F_ENCRYPTED_AES256 0x00000008 /* Encrypted using AES256. */
#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */
#define IMAGE_F_RAM_LOAD 0x00000020/** Image trailer TLV types.*/
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */
#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */
#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */
#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */
#define IMAGE_TLV_ED25519 0x24 /* ED25519 of hash output */
#define IMAGE_TLV_SIG_PURE 0x25 /* If true then any signature found has beencalculated over image directly. */
#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */
#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW-128 or256 */
#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-P256 */
#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */
#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */
#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */
ih_hdr_size:?
字段表示頭部的長度,因此表示Image本身的偏移量。這個字段提供了向后兼容性,以防更改Image頭的格式。
ih_protect_tlv_size:? ?
字段表示TLV保護區域的長度。如果存在受保護的TLV,則必須存在一個magic等于IMAGE_TLV_PROT_INFO_MAGIC的TLV信息頭,并且受保護的TLV(加上信息頭本身)必須包含在哈希計算中。否則,哈希值只計算Image標題和Image本身。
在此例中,ih_protect_tlv_size字段的值為0。
2.2 Flash Map
設備的閃存根據其閃存映射進行分區。在高層次上,flash映射將數字id映射到flash區域。閃存區是磁盤的一個區域,具有以下屬性:
1)?一個區域可以完全擦除而不影響任何其他區域
2)?對一個區域的寫入不限制對其他區域的寫入。
引導加載程序使用以下flash區域id:
/* Independent from multiple image boot */
#define FLASH_AREA_BOOTLOADER 0
#define FLASH_AREA_IMAGE_SCRATCH 3
/* If the bootloader is working with the first image */
#define FLASH_AREA_IMAGE_PRIMARY 1
#define FLASH_AREA_IMAGE_SECONDARY 2
/* If the bootloader is working with the second image */
#define FLASH_AREA_IMAGE_PRIMARY 5
#define FLASH_AREA_IMAGE_SECONDARY 6
引導加載程序區域包含引導加載程序映像本身。其他方面將在后面的部分中描述。閃存可以包含多個可執行映像,因此主區域和輔助區域的閃存區域id是根據活動映像(引導加載程序當前正在其上工作)的數量映射的。
2.3 Image的槽
閃存的一部分可劃分為多個Image區域,每個Image區域包含兩個Image插槽:
1)主插槽
2)輔助插槽
正常情況下,引導加載程序只會從主插槽運行Image,因此必須構建映像,使它們能夠從flash中的固定位置運行(這方面的例外是direct-xip和ram-load升級模式)。如果引導加載程序需要運行駐留在輔助插槽中的映像,那么它必須在這樣做之前將其內容復制到主插槽中,要么交換兩個映像,要么覆蓋主插槽的內容。
2.4 使用scratch交換
當使用使用scratch交換算法時,除了Image區域的插槽之外,引導加載程序還需要scratch區域來允許可靠的Image交換。scratch區必須具有足夠的大小,至少可以存儲將要交換的最大扇區。許多設備都有同樣大小的小扇區,例如4K,而其他設備則有可變大小的扇區,其中最大的扇區可能是128K或256K,因此scratch必須足夠大才能存儲這些扇區。
scratch只在交換固件時使用,這意味著只在進行升級時使用。考慮到這一點,使用更大尺寸的劃痕的主要原因是閃存磨損將更均勻地分布,因為單個扇區的寫入次數是使用兩個扇區的兩倍,例如。為您的用例評估劃痕的理想大小,以下參數是相關的:
- the ratio of image size / scratch size
- the number of erase cycles supported by the flash hardware
?2.5 Image 尾部數據結構
為了使引導加載程序能夠確定當前狀態以及在當前引導操作期間應該采取什么操作,它使用存儲在映像閃存區域中的元數據。在交換時,其中一些元數據被臨時復制到刮痕區或從scratch區復制出來。
這個元數據位于Inage區域的末尾,稱為Image trailer。其具體結構如下:
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+~ ~~ Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3) ~~ ~+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Encryption key 0 (16 octets) [*] || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 0xff padding as needed || (BOOT_MAX_ALIGN minus 16 octets from Encryption key 0) [*] |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Encryption key 1 (16 octets) [*] || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 0xff padding as needed || (BOOT_MAX_ALIGN minus 16 octets from Encryption key 1) [*] |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Swap size (4 octets) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 0xff padding as needed || (BOOT_MAX_ALIGN minus 4 octets from Swap size) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Swap info | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Copy done | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Image OK | 0xff padding (BOOT_MAX_ALIGN minus 1 octet) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 0xff padding as needed || (BOOT_MAX_ALIGN minus 16 octets from MAGIC) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| MAGIC (16 octets) || |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
?1)Swap info
交換信息:單個字節,編碼以下信息:
交換類型:0 ~ 3位存儲。指示正在進行的交換操作的類型。當MCUboot恢復被中斷的交換時,它使用這個字段來確定要執行的操作類型。該字段包含下表中下列值之一。
圖像號:存儲在4-7位。它在單映像引導時總是0值。在多映像引導的情況下,它指示中斷發生時交換了哪個映像。在所有圖像交換操作期間使用相同的劃痕區域。因此使用該字段
Name | Value |
---|---|
BOOT_SWAP_TYPE_TEST | 2 |
BOOT_SWAP_TYPE_PERM | 3 |
BOOT_SWAP_TYPE_REVERT | 4 |
BOOT_SWAP_TYPE_TEST
是嵌入式系統中固件升級機制的一部分,通常用于測試固件鏡像的交換功能。以下是其主要功能的詳細介紹:
BOOT_SWAP_TYPE_TEST
是一種啟動交換類型,主要用于:
測試新固件鏡像的可靠性
驗證固件升級流程
在不永久提交新固件的情況下進行測試
典型工作流程
標記狀態:系統將當前固件標記為"測試"狀態
交換鏡像:引導加載程序(bootloader)會加載新固件進行測試
驗證階段:新固件運行一段時間進行驗證
結果處理:
如果測試成功,系統可能將狀態改為永久
如果測試失敗,系統會回退到舊固件
使用場景
安全關鍵的固件升級前驗證
A/B分區系統中的測試啟動
開發階段的固件驗證
現場設備的安全升級測試
優勢
安全性:避免直接升級可能導致設備變磚
可靠性:確保新固件穩定后再永久應用
靈活性:開發人員可以測試不同版本的固件
實現細節
具體實現可能因系統而異,但通常涉及:
引導加載程序中的特殊處理邏輯
非易失性存儲器中的狀態標志
鏡像完整性檢查機制
超時或條件觸發的回退機制
2)拷貝完成:單字節表示該槽中的映像是否完成(0x01=done;0 xff =沒有完成)。
3)image OK:一個單字節,表示這個槽中的映像是否已被用戶確認為好的(0x01=confirmed;0 xff =沒有證實)。
4)MAGIC:標識Image trailer布局的16字節字段。它可以根據映像支持的最大寫對齊(BOOT_MAX_ALIGN)假設不同的值,由以下結構定義:
union boot_img_magic_t
{struct {uint16_t align;uint8_t magic[14];};uint8_t val[16];
};
如果BOOT_MAX_ALIGN是8字節,那么MAGIC包含以下16字節:
const union boot_img_magic_t boot_img_magic = {.val = {0x77, 0xc2, 0x95, 0xf3,0x60, 0xd2, 0xef, 0x7f,0x35, 0x52, 0x50, 0x0f,0x2c, 0xb6, 0x79, 0x80}
};
如果BOOT_MAX_ALIGN被定義為任何不同于8的值,那么支持的最大寫對齊值將在MAGIC字段中編碼,后跟一個固定的14字節模式:
const union boot_img_magic_t boot_img_magic = {.align = BOOT_MAX_ALIGN,.magic = {0x2d, 0xe1,0x5d, 0x29, 0x41, 0x0b,0x8d, 0x77, 0x67, 0x9c,0x11, 0x0f, 0x1f, 0x8a}
};
3 交換區
3.1 單交換區
對于新的交換,MCUboot必須檢查一個字段集合,以確定執行哪個交換操作。
Image trailers記錄是圍繞flash硬件施加的限制構建的。因此,它們沒有一個非常直觀的設計,并且很難通過查看圖像預告片來了解設備的狀態。最好通過一組表將所有可能的跟蹤狀態映射到上面描述的交換類型。這些表格轉載如下。
State I (swap using offset only)| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any | Good |image-ok | Any | Unset |copy-done | Any | Set |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_REVERT |-------------------------------------------------'State II| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any | Good |image-ok | Any | Unset |copy-done | Any | Any |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_TEST |-------------------------------------------------'State III| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any | Good |image-ok | Any | 0x01 |copy-done | Any | Any |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_PERM |-------------------------------------------------'State IV| primary slot | secondary slot |-----------------+--------------+----------------|magic | Good | Any |image-ok | 0xff | Any |copy-done | 0x01 | Any |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_REVERT |-------------------------------------------------'
上述三種狀態中的任何一種都會導致MCUboot嘗試交換Image。否則,MCUboot不會嘗試交換映像,從而導致其他三種交換類型之一,如狀態IV所示。
State V| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any | Any |image-ok | Any | Any |copy-done | Any | Any |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_NONE, |BOOT_SWAP_TYPE_FAIL, or |BOOT_SWAP_TYPE_PANIC |-------------------------------------------------'
?3.2 Multiple Image boot?
當閃存包含多個可執行映像時,引導加載程序的操作稍微復雜一些,但與前面描述的使用一個映像的過程類似。每個圖像都可以獨立更新,因此閃存進一步分區,為每個圖像安排兩個插槽。
+--------------------+
| MCUboot |
+--------------------+~~~~~ <- memory might be not contiguous
+--------------------+
| Image 0 |
| primary slot |
+--------------------+
| Image 0 |
| secondary slot |
+--------------------+~~~~~ <- memory might be not contiguous
+--------------------+
| Image N |
| primary slot |
+--------------------+
| Image N |
| secondary slot |
+--------------------+
| Scratch |
+--------------------+
3.3 Image交換
?引導程序交換兩個映像槽的內容有兩個原因:
1) 用戶發出了“設置掛起”操作;次要插槽中的映像應該運行一次(狀態I)或重復運行一次(狀態II),這取決于是否指定了永久交換。
2) 測試映像在未確認的情況下重啟;引導加載程序應該恢復到當前在輔助插槽中的原始映像(狀態III)。
?如果映像顯示應該運行輔助插槽中的映像,則引導加載程序需要將其復制到主插槽。當前在主插槽中的映像也需要保留在flash中,以便以后使用。此外,如果引導加載程序在交換操作中重置,則兩個映像都需要是可恢復的。按照以下步驟交換兩個鏡像:
Step-1:?確定兩個插槽是否足夠兼容以交換它們的映像。為了兼容,兩者都必須只有能夠容納劃痕區域的扇區,如果其中一個扇區比另一個扇區大,它必須能夠完全容納來自另一個插槽的某些四舍五入扇區。在接下來的步驟中,我們將使用術語“區域”來表示復制/擦除的數據總量,因為這可以是任何數量的扇區,這取決于有多少扇區能夠適合某些交換操作。
Step-2:?按降序迭代區域索引列表(即從最大索引開始);僅復制預定為圖像一部分的區域;當前元素= "index"。
a.擦除劃痕區域。
b.將secondary_slot[index]拷貝到劃痕區。
如果這是槽中的最后一個區域,則刮擦區域具有初始化以存儲初始狀態的臨時狀態區域,因為必須擦除主槽的最后一個區域。在這種情況下,只復制計算為圖像的數據。
否則,如果這是交換的第一個區域,但不是槽中的最后一個區域,則初始化主槽中的狀態區域并復制完整的區域內容。否則,復制整個區域的內容。c.寫入更新后的swap狀態(i)。
d.擦除secondary_slot[index]e.將primary_slot[index]拷貝到secondary_slot[index]。
如果這不是槽中的最后一個區域,則擦除輔助槽中的預告片,以始終使用主槽中的預告片。
f.寫入更新后的swap狀態(ii)。
g.擦除primary_slot[index]。
h.將刮痕區復制到primary_slot[index]中,根據之前在步驟b中復制的數量。如果這是槽中的最后一個區域,則從頭讀取狀態(它臨時存儲在那里),然后在主槽中重新寫入狀態
Step-3:? 將交換過程的完成持久化到主插槽映像 trailer。
注意點:?
步驟2-f中的附加警告是必要的,以便用戶可以在稍后的時間寫入輔助插槽映像預告片。在不寫入映像預告片的情況下,用戶可以在二級插槽中測試映像(即切換到狀態I)。
步驟3的細節取決于是否正在測試映像、永久使用映像、恢復映像或在請求交換時發生了輔助插槽的驗證失敗:
* test:o Write primary_slot.copy_done = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGICsecondary_slot.magic = UNSETprimary_slot.image_ok = Unset)* permanent:o Write primary_slot.copy_done = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGICsecondary_slot.magic = UNSETprimary_slot.image_ok = 0x01)* revert:o Write primary_slot.copy_done = 1o Write primary_slot.image_ok = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGIC)* failure to validate the secondary slot:o Write primary_slot.image_ok = 1
4??交換狀態(swap status)
交換狀態區域允許引導加載程序在映像交換操作中間重新啟動時進行恢復。交換狀態區域由一系列單字節記錄組成。這些記錄是獨立寫入的,因此必須根據flash硬件施加的最小寫入大小進行填充。交換狀態區域的結構如下所示。在該圖中,為了簡單起見,假設最小寫大小為1,該圖顯示了每個扇區的3種狀態,適用于使用scratch交換和使用move交換,但是在使用offset交換模式中只有3種狀態。
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec125,state 2 | |+-+-+-+-+-+-+-+-+ +~ ~~ [Records for indices 124 through 1 ~~ ~~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+~ |sec000,state 0 |sec000,state 1 |sec000,state 2 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
?以上可能一點幫助都沒有;這里有一段英文描述。
每個映像槽被劃分成一系列的閃存扇區。如果我們枚舉單個槽中的扇區,從0開始,我們將得到一個扇區索引列表。由于有兩個映像槽,每個扇區索引將對應一對扇區。例如,扇區索引0分別對應主槽位的第一個扇區和從槽位的第一個扇區。最后,反轉索引列表,使列表以索引BOOT_MAX_IMG_SECTORS - 1開始,以0結束。
在交換操作期間,每個扇區索引通過四個不同的狀態轉換:
0. primary slot: image 0, secondary slot: image 1, scratch: N/A
1. primary slot: image 0, secondary slot: N/A, scratch: image 1 (1->s, erase 1)
2. primary slot: N/A, secondary slot: image 0, scratch: image 1 (0->1, erase 0)
3. primary slot: image 1, secondary slot: image 0, scratch: N/A (s->0)
?每次扇區索引轉換到新狀態時,引導加載程序都會向交換狀態區域寫入一條記錄。邏輯上,引導加載程序只需要每個扇區索引一個記錄來跟蹤當前的交換狀態。然而,由于flash硬件的限制,當索引狀態改變時,不能重寫記錄。為了解決這個問題,引導加載程序為每個扇區索引使用三條記錄,而不是一條。
每個部門-狀態對表示為一組三條記錄。記錄值映射到上述四種狀態如下所示:
| rec0 | rec1 | rec2--------+------+------+------state 0 | 0xff | 0xff | 0xffstate 1 | 0x01 | 0xff | 0xffstate 2 | 0x01 | 0x02 | 0xffstate 3 | 0x01 | 0x02 | 0x03
?5 復位覆蓋
如果引導加載程序在交換操作中重置,則兩個Image可能在flash中不連續。Bootutil通過使用Image起始數據來確定Image部分如何在flash中分布來從這種情況中恢復。
第一步是確定相關交換狀態區域的位置。由于該區域嵌入到映像槽中,因此在交換操作期間,它在閃存中的位置會發生變化。下面的一組表將圖像預告片內容映射到交換狀態位置。在這些表中,“source”字段表示交換狀態區域的位置。在多IMage啟動的情況下,總是成對地檢查圖像的主區和單劃痕區。如果在劃痕區域找到交換狀態,那么它可能不屬于當前IMage。交換狀態的swap_info字段存儲相應的信息.
| primary slot | scratch |----------+--------------+--------------|magic | Good | Any |copy-done | 0x01 | N/A |----------+--------------+--------------'source: none |----------------------------------------'| primary slot | scratch |----------+--------------+--------------|magic | Good | Any |copy-done | 0xff | N/A |----------+--------------+--------------'source: primary slot |----------------------------------------'| primary slot | scratch |----------+--------------+--------------|magic | Any | Good |copy-done | Any | N/A |----------+--------------+--------------'source: scratch |----------------------------------------'| primary slot | scratch |----------+--------------+--------------|magic | Unset | Any |copy-done | 0xff | N/A |----------+--------------+--------------|source: primary slot |----------------------------------------+------------------------------+This represents one of two cases: |o No swaps ever (no status to read, so no harm in checking). |o Mid-revert; status in the primary slot. |For this reason we assume the primary slot as source, to trigger a |check of the status area and find out if there was swapping under way. |-----------------------------------------------------------------------'
如果交換狀態區域表明映像不是連續的,那么MCUboot通過讀取活動映像尾片中的交換信息字段并從0-3位提取交換類型來確定被中斷的交換操作的類型,然后恢復操作。換句話說,它應用前一節中定義的過程,將映像1移動到主插槽中,將映像0移動到輔助插槽中。如果引導狀態表明在刮擦區域中存在映像部分,則從區域交換過程中的步驟e或步驟h開始將該部分復制到正確的位置。?