B. Example usage

Warning

These examples are for illustrative purposes only and are not guaranteed to compile. Many error codes are not handled in order to keep the examples brief. A real implementation will need to initialize variables appropriately and handle failures as they see fit.

B.1. Retrieve versions of installed images

This example shows the retrieval of image versions for all components.

 1   #include <psa/update.h>
 2   
 3   /* Assume that the components in this system have sequential identifiers
 4    * starting at zero.
 5    */
 6   #define NUM_COMPONENTS 3
 7   
 8   void example_get_installation_info() {
 9   
10       psa_status_t rc;
11       psa_fwu_component_t id;
12       psa_fwu_component_info_t info;
13   
14       for (id = 0; id < NUM_COMPONENTS; ++id) {
15           rc = psa_fwu_query(id, &info);
16   
17           if (rc == PSA_SUCCESS) {
18               specific_protocol_report(id, info.version);
19           }
20       }
21   }

B.2. Individual component update (single part operation)

This example shows the installation of a single component that is smaller than PSA_FWU_MAX_WRITE_SIZE.

 1   #include <psa/update.h>
 2   
 3   /* Simple, single image update with a bundled manifest.
 4    * Component requires reboot
 5    */
 6   
 7   void example_install_single_image(psa_fwu_component_t id,
 8                                     const void *image, size_t image_size) {
 9       psa_status_t rc;
10   
11       // Assume the component state is READY
12       rc = psa_fwu_start(id, NULL, 0);
13   
14       if (rc == PSA_SUCCESS) {
15           rc = psa_fwu_write(id, 0, image, image_size);
16   
17           if (rc == PSA_SUCCESS) {
18               rc = psa_fwu_finish(id);
19   
20               if (rc == PSA_SUCCESS) {
21                   rc = psa_fwu_install();
22   
23                   if (rc == PSA_SUCCESS_REBOOT) {
24                       // do other things and then eventually...
25                       psa_fwu_request_reboot();
26                       return;     // or wait for reboot to happen
27                   }
28               }
29           }
30           // an error occurred during image preparation: clean up
31           psa_fwu_cancel(id);
32           psa_fwu_clean(id);
33       }
34       // report failure...
35   }

B.3. Individual component update (multi part operation)

This example shows the installation of a component that can be larger than PSA_FWU_MAX_WRITE_SIZE, and requires writing in multiple blocks.

 1   #include <psa/update.h>
 2   #include <stdlib.h>
 3   #include <stddef.h>
 4   
 5   /* Single image update with a bundled manifest.
 6    * Image data is fetched and written incrementally in blocks
 7    */
 8   
 9   void example_install_single_image_multipart(psa_fwu_component_t id,
10                                               size_t total_image_size) {
11       psa_status_t rc;
12       size_t offset;
13       size_t to_send;
14       void *image;
15   
16       // Assume the component state is READY
17       rc = psa_fwu_start(id, NULL, 0);
18   
19       if (rc == PSA_SUCCESS) {
20           // Using dynamically allocated memory for this example
21   
22           image = malloc(PSA_FWU_MAX_WRITE_SIZE);
23           if (image == NULL) {
24               rc == PSA_ERROR_INSUFFICIENT_MEMORY;
25           } else {
26               for (offset = 0;
27                   offset < total_image_size,
28                   offset += PSA_FWU_MAX_WRITE_SIZE) {
29                   to_send = min(PSA_FWU_MAX_WRITE_SIZE, total_image_size - offset);
30                   if (fetch_next_part_of_image(id, image, to_send)) {
31                       // failed to obtain next block of image
32                       rc == PSA_ERROR_GENERIC_ERROR;
33                       break;
34                   } else {
35                       rc = psa_fwu_write(id, offset, image, to_send);
36                       if (rc != PSA_SUCCESS) {
37                           break;
38                       }
39                   }
40               }
41               free(image);
42           }
43   
44           if (rc == PSA_SUCCESS) {
45               rc = psa_fwu_finish(id);
46   
47               if (rc == PSA_SUCCESS) {
48                   rc = psa_fwu_install();
49   
50                   if (rc == PSA_SUCCESS) {
51                       // installation completed, now clean up
52                       psa_fwu_clean(id);
53                       // report success ...
54                       return;
55                   } else if (rc == PSA_SUCCESS_REBOOT) {
56                       // do other things and then eventually...
57                       psa_fwu_request_reboot();
58                       return;     // or wait for reboot to happen
59                   }
60               }
61           }
62           // an error occurred during image preparation: clean up
63           psa_fwu_cancel(id);
64           psa_fwu_clean(id);
65       }
66       // report failure...
67   }

B.4. Multiple components with dependent images

This example shows how multiple components can be installed together. This is required if the images are inter-dependent, and it is not possible to install them in sequence because of the dependencies.

Note

Not all implementations that have multiple components support this type of multi-component update.

 1   #include <psa/update.h>
 2   
 3   /* Atomic, multiple image update, with bundled manifests.
 4    * Installation requires reboot
 5    */
 6   
 7   // Prepare a single image for update
 8   static psa_status_t prepare_image(psa_fwu_component_t id,
 9                              const void *image, size_t image_size) {
10       psa_status_t rc;
11   
12       // Assume the component state is READY
13       rc = psa_fwu_start(id, NULL, 0);
14   
15       if (rc == PSA_SUCCESS) {
16           rc = psa_fwu_write(id, 0, image, image_size);
17   
18           if (rc == PSA_SUCCESS) {
19               rc = psa_fwu_finish(id);
20   
21           if (rc != PSA_SUCCESS) {
22               // an error occurred during image preparation: clean up
23               psa_fwu_cancel(id);
24               psa_fwu_clean(id);
25           }
26       }
27       return rc;
28   }
29   
30   // Fetch and prepare a single image for update
31   static psa_status_t fetch_and_prepare_image(psa_fwu_component_t id) {
32       psa_status_t rc;
33       void *image;
34       size_t image_size;
35   
36       // Get image data.
37       // Assume this is dynamically allocated memory in this example
38       image = fetch_image_data(id, &image_size);
39       if (image == NULL)
40           return PSA_ERROR_INSUFFICIENT_MEMORY;
41   
42       rc = prepare_image(id, image, image_size);
43       free(image);
44       return rc;
45   }
46   
47   // Update a set of components atomically
48   // Prepare all the images before installing
49   // Clean up all preparation on error
50   void example_install_multiple_images(psa_fwu_component_id ids[],
51                                        size_t num_ids) {
52       psa_status_t rc;
53       int ix;
54   
55       for (ix = 0, ix < num_ids; ++ix) {
56           rc = fetch_and_prepare_image(ids[ix]);
57           if (rc != PSA_SUCCESS)
58               break;
59       }
60   
61       if (rc == PSA_SUCCESS) {
62           // All images are prepared, so now install them
63           rc = psa_fwu_install();
64   
65           if (rc == PSA_SUCCESS_REBOOT) {
66               // do other things and then eventually...
67               psa_fwu_request_reboot();
68               return;     // or wait for reboot to happen
69           }
70       }
71       // an error occurred during image preparation: clean up.
72       // All of the components prior to element ix have been prepared
73       // Update of these needs to be aborted and erased.
74       while (--ix >= 0) {
75           psa_fwu_cancel(ids[ix]);
76           psa_fwu_clean(ids[ix]);
77       }
78       // Report the failure ...
79   }

B.5. Clean up all component updates

This example removes any prepared and failed update images for all components.

 1   #include <psa/update.h>
 2   
 3   /* Assume that the components in this system have sequential identifiers
 4    * starting at zero.
 5    */
 6   #define NUM_COMPONENTS 3
 7   
 8   /* Forcibly cancel and clean up all components to return to READY state */
 9   
10   void example_clean_all_components() {
11   
12       psa_status_t rc;
13       psa_fwu_component_t id;
14       psa_fwu_component_info_t info;
15   
16       rc = psa_fwu_reject();
17       if (rc == PSA_SUCCESS_REBOOT) {
18           psa_fwu_request_reboot();
19           // After reboot, run this function again to finish clean up
20           return;
21       }
22   
23       for (id = 0; id < NUM_COMPONENTS; ++id) {
24           rc = psa_fwu_query(id, &info);
25   
26           if (rc == PSA_SUCCESS) {
27               switch (info.state) {
28                  case PSA_FWU_WRITING:
29                  case PSA_FWU_CANDIDATE:
30                     psa_fwu_cancel(id);
31                     psa_fwu_clean(id);
32                     break;
33                  case PSA_FWU_FAILED:
34                  case PSA_FWU_UPDATED:
35                     psa_fwu_clean(id);
36                     break;
37               }
38           }
39       }
40   }