@@ -1608,6 +1608,198 @@ boot_set_image_ok(void)
16081608}
16091609#endif /* !MCUBOOT_OVERWRITE_ONLY */
16101610
1611+ #if (BOOT_IMAGE_NUMBER > 1 )
1612+ /**
1613+ * Check the image dependency whether it is satisfied and modify
1614+ * the swap type if necessary.
1615+ *
1616+ * @param dep Image dependency which has to be verified.
1617+ *
1618+ * @return 0 on success; nonzero on failure.
1619+ */
1620+ static int
1621+ boot_verify_single_dependency (struct image_dependency * dep )
1622+ {
1623+ struct image_version * dep_version ;
1624+ size_t dep_slot ;
1625+ int rc ;
1626+
1627+ /* Determine the source of the image which is the subject of
1628+ * the dependency and get it's version. */
1629+ dep_slot = (boot_data .swap_type [dep -> image_id ] != BOOT_SWAP_TYPE_NONE ) ?
1630+ BOOT_SECONDARY_SLOT : BOOT_PRIMARY_SLOT ;
1631+ dep_version = & boot_data .imgs [dep -> image_id ][dep_slot ].hdr .ih_ver ;
1632+
1633+ rc = boot_is_version_sufficient (& dep -> image_min_version , dep_version );
1634+ if (rc != 0 ) {
1635+ /* Dependency not satisfied.
1636+ * Modify the swap type to decrease the version number of the image
1637+ * (which will be located in the primary slot after the boot process),
1638+ * consequently the number of unsatisfied dependencies will be
1639+ * decreased or remain the same.
1640+ */
1641+ switch (BOOT_SWAP_TYPE (& boot_data )) {
1642+ case BOOT_SWAP_TYPE_TEST :
1643+ case BOOT_SWAP_TYPE_PERM :
1644+ BOOT_SWAP_TYPE (& boot_data ) = BOOT_SWAP_TYPE_NONE ;
1645+ break ;
1646+ case BOOT_SWAP_TYPE_NONE :
1647+ BOOT_SWAP_TYPE (& boot_data ) = BOOT_SWAP_TYPE_REVERT ;
1648+ break ;
1649+ default :
1650+ break ;
1651+ }
1652+ }
1653+
1654+ return rc ;
1655+ }
1656+
1657+ /**
1658+ * Read all dependency TLVs of an image from the flash and verify
1659+ * one after another to see if they are all satisfied.
1660+ *
1661+ * @param slot Image slot number.
1662+ *
1663+ * @return 0 on success; nonzero on failure.
1664+ */
1665+ static int
1666+ boot_verify_all_dependency (uint32_t slot )
1667+ {
1668+ const struct flash_area * fap ;
1669+ struct image_header * hdr ;
1670+ struct image_tlv_info info ;
1671+ struct image_tlv tlv ;
1672+ struct image_dependency dep ;
1673+ uint32_t off ;
1674+ uint32_t end ;
1675+ bool dep_tlvs_found = false;
1676+ int rc ;
1677+
1678+ rc = flash_area_open (flash_area_id_from_image_slot (slot ), & fap );
1679+ if (rc != 0 ) {
1680+ rc = BOOT_EFLASH ;
1681+ goto done ;
1682+ }
1683+
1684+ hdr = boot_img_hdr (& boot_data , slot );
1685+ /* The TLVs come after the image. */
1686+ off = hdr -> ih_hdr_size + hdr -> ih_img_size ;
1687+
1688+ /* The TLV area always starts with an image_tlv_info structure. */
1689+ rc = flash_area_read (fap , off , & info , sizeof (info ));
1690+ if (rc != 0 ) {
1691+ rc = BOOT_EFLASH ;
1692+ goto done ;
1693+ }
1694+
1695+ if (info .it_magic != IMAGE_TLV_INFO_MAGIC ) {
1696+ rc = BOOT_EBADIMAGE ;
1697+ goto done ;
1698+ }
1699+ end = off + info .it_tlv_tot ;
1700+ off += sizeof (info );
1701+
1702+ /* Traverse through all of the TLVs to find the dependency TLVs. */
1703+ for (; off < end ; off += sizeof (tlv ) + tlv .it_len ) {
1704+ rc = flash_area_read (fap , off , & tlv , sizeof (tlv ));
1705+ if (rc != 0 ) {
1706+ rc = BOOT_EFLASH ;
1707+ goto done ;
1708+ }
1709+
1710+ if (tlv .it_type == IMAGE_TLV_DEPENDENCY ) {
1711+ if (!dep_tlvs_found ) {
1712+ dep_tlvs_found = true;
1713+ }
1714+
1715+ if (tlv .it_len != sizeof (dep )) {
1716+ rc = BOOT_EBADIMAGE ;
1717+ goto done ;
1718+ }
1719+
1720+ rc = flash_area_read (fap , off + sizeof (tlv ), & dep , tlv .it_len );
1721+ if (rc != 0 ) {
1722+ rc = BOOT_EFLASH ;
1723+ goto done ;
1724+ }
1725+
1726+ /* Verify dependency and modify the swap type if not satisfied. */
1727+ rc = boot_verify_single_dependency (& dep );
1728+ if (rc != 0 ) {
1729+ /* Dependency not satisfied. */
1730+ goto done ;
1731+ }
1732+
1733+ /* Dependency satisfied, no action needed.
1734+ * Continue with the next TLV entry.
1735+ */
1736+ } else if (dep_tlvs_found ) {
1737+ /* The dependency TLVs are contiguous in the TLV area. If a
1738+ * dependency had already been found and the last read TLV
1739+ * has a different type then there are no more dependency TLVs.
1740+ * The search can be finished.
1741+ */
1742+ break ;
1743+ }
1744+ }
1745+
1746+ done :
1747+ flash_area_close (fap );
1748+ return rc ;
1749+ }
1750+
1751+ /**
1752+ * Verify whether the image dependencies in the TLV area are
1753+ * all satisfied and modify the swap type if necessary.
1754+ *
1755+ * @return 0 if all dependencies are satisfied,
1756+ * nonzero otherwise.
1757+ */
1758+ static int
1759+ boot_verify_single_image_dependency (void )
1760+ {
1761+ size_t slot ;
1762+
1763+ /* Determine the source of the dependency TLVs. Those dependencies have to
1764+ * be checked which belong to the image that will be located in the primary
1765+ * slot after the firmware update process.
1766+ */
1767+ if (BOOT_SWAP_TYPE (& boot_data ) != BOOT_SWAP_TYPE_NONE &&
1768+ BOOT_SWAP_TYPE (& boot_data ) != BOOT_SWAP_TYPE_FAIL ) {
1769+ slot = BOOT_SECONDARY_SLOT ;
1770+ } else {
1771+ slot = BOOT_PRIMARY_SLOT ;
1772+ }
1773+
1774+ return boot_verify_all_dependency (slot );
1775+ }
1776+
1777+ /**
1778+ * Iterate over all the images and verify whether the image dependencies in the
1779+ * TLV area are all satisfied and update the related swap type if necessary.
1780+ */
1781+ static void
1782+ boot_verify_all_image_dependency (void )
1783+ {
1784+ current_image = 0 ;
1785+ int rc ;
1786+
1787+ while (current_image < BOOT_IMAGE_NUMBER ) {
1788+ rc = boot_verify_single_image_dependency ();
1789+ if ( rc == 0 ) {
1790+ /* All dependencies've been satisfied, continue with next image. */
1791+ current_image ++ ;
1792+ } else if (rc == BOOT_EBADVERSION ) {
1793+ /* Dependency check needs to be restarted. */
1794+ current_image = 0 ;
1795+ } else {
1796+ /* Other error happened, images are inconsistent */
1797+ return ;
1798+ }
1799+ }
1800+ }
1801+ #endif /* (BOOT_IMAGE_NUMBER > 1) */
1802+
16111803/**
16121804 * Performs a clean (not aborted) image update.
16131805 *
@@ -1966,6 +2158,13 @@ boot_go(struct boot_rsp *rsp)
19662158 boot_prepare_image_for_update (& bs );
19672159 }
19682160
2161+ #if (BOOT_IMAGE_NUMBER > 1 )
2162+ /* Iterate over all the images and verify whether the image dependencies
2163+ * are all satisfied and update swap type if necessary.
2164+ */
2165+ boot_verify_all_image_dependency ();
2166+ #endif
2167+
19692168 /* Iterate over all the images. At this point there are no aborted swaps
19702169 * and the swap types are determined for each image. By the end of the loop
19712170 * all required update operations will have been finished.
0 commit comments