CC312: Allow OTP reads to be more flexible

Allow partial reads of OTP items. Also, fix a minor bug with reading and
writing larger OTP items.

Change-Id: I3e037dbff1e59e9c0b0df347b350de0fffdb2a57
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/platform/ext/accelerator/cc312/otp_cc312.c b/platform/ext/accelerator/cc312/otp_cc312.c
index e82616a..27ee2b4 100644
--- a/platform/ext/accelerator/cc312/otp_cc312.c
+++ b/platform/ext/accelerator/cc312/otp_cc312.c
@@ -240,18 +240,15 @@
 
 
 
-static enum tfm_plat_err_t otp_read(const uint8_t *addr, size_t size,
+static enum tfm_plat_err_t otp_read(const uint8_t *addr, size_t item_size,
                                     size_t out_len, uint8_t *out)
 {
     uint32_t* word_ptr;
     uint32_t word;
     uint32_t start_offset;
-    uint8_t out_done;
+    size_t out_done;
     size_t copy_size;
-
-    if (out_len < size) {
-        return TFM_PLAT_ERR_INVALID_INPUT;
-    }
+    size_t total_copy_size = item_size < out_len ? item_size : out_len;
 
     /* CC312 OTP can only be read / written in 32 bit words. In order to allow
      * access to unaligned uint8_t pointers (as per the function definition):
@@ -267,15 +264,15 @@
      * the last word. This is checked for all words, in case the first word is
      * also the last word.
      */
-    for(out_done = 0; out_done < size;) {
+    for(out_done = 0; out_done < total_copy_size;) {
         start_offset = ((uint32_t)addr + out_done) & 0x3;
         word_ptr = (uint32_t*)(addr + out_done - start_offset);
 
         word = *word_ptr;
 
         copy_size = sizeof(word) - start_offset;
-        if (out_done + copy_size > size) {
-            copy_size = size - out_done;
+        if (out_done + copy_size > total_copy_size) {
+            copy_size = total_copy_size - out_done;
         }
 
 
@@ -322,7 +319,7 @@
     uint32_t current_word;
     uint32_t word;
     uint32_t start_offset;
-    uint8_t in_done = 0;
+    size_t in_done = 0;
     size_t copy_size;
     uint16_t zero_count;
 
@@ -602,6 +599,7 @@
     case PLAT_OTP_ID_HUK:
         return otp_read(otp->huk, sizeof(otp->huk), out_len, out);
     case PLAT_OTP_ID_IAK:
+        /* The IAK is stored in the rot_public_key slot */
         return otp_read(otp->rot_public_key,
                         sizeof(otp->rot_public_key), out_len, out);
 
@@ -790,6 +788,7 @@
         return otp_write(otp->huk, sizeof(otp->huk), in_len, in,
                          (uint8_t*)&otp->icv_programmed_flags.huk_zero_bits);
     case PLAT_OTP_ID_IAK:
+        /* The IAK is stored in the rot_public_key slot */
         return otp_write(otp->rot_public_key, sizeof(otp->rot_public_key),
                          in_len, in,
                          (uint8_t*)&otp->oem_programmed_flags.oem_rot_public_key_zero_bits);
@@ -880,6 +879,7 @@
         *size = sizeof(otp->huk);
         break;
     case PLAT_OTP_ID_IAK:
+        /* The IAK is stored in the rot_public_key slot */
         *size = sizeof(otp->rot_public_key);
         break;
 
diff --git a/platform/ext/common/template/otp_flash.c b/platform/ext/common/template/otp_flash.c
index 56ffce7..df630f4 100644
--- a/platform/ext/common/template/otp_flash.c
+++ b/platform/ext/common/template/otp_flash.c
@@ -125,14 +125,16 @@
         return err;
     }
 
-    copy_size = in_len < value_size ? in_len : value_size;
+    if (in_len > value_size) {
+        return TFM_PLAT_ERR_INVALID_INPUT;
+    }
 
-    err = read_otp_nv_counters_flash(offset, buffer, copy_size);
+    err = read_otp_nv_counters_flash(offset, buffer, in_len);
     if (err != TFM_PLAT_ERR_SUCCESS) {
         return err;
     }
 
-    for (idx = 0; idx < copy_size; idx++) {
+    for (idx = 0; idx < in_len; idx++) {
         if ((buffer[idx] | in[idx]) != in[idx]) {
             return TFM_PLAT_ERR_INVALID_INPUT;
         }
@@ -140,7 +142,7 @@
         buffer[idx] |= in[idx];
     }
 
-    err = write_otp_nv_counters_flash(offset, buffer, copy_size);
+    err = write_otp_nv_counters_flash(offset, buffer, in_len);
     if (err != TFM_PLAT_ERR_SUCCESS) {
         return err;
     }
diff --git a/platform/include/tfm_plat_otp.h b/platform/include/tfm_plat_otp.h
index 5773904..783515c 100644
--- a/platform/include/tfm_plat_otp.h
+++ b/platform/include/tfm_plat_otp.h
@@ -89,6 +89,11 @@
  *                                      into in bytes.
  * \param[out] out                      Buffer to read the element into.
  *
+ * \note                                If the size of the internal OTP
+ *                                      representation of the item is different
+ *                                      to out_len, then the smaller of the two
+ *                                      is the amount of bytes that must be
+ *                                      read.
  *
  * \retval TFM_PLAT_ERR_SUCCESS         The element is read successfully.
  * \retval TFM_PLAT_ERR_UNSUPPORTED     The given element has not been
@@ -116,6 +121,12 @@
  *                                      function should return an error code and
  *                                      not alter the contents of OTP memory.
  *
+ * \note                                If the size of the internal OTP
+ *                                      representation of the item is smaller
+ *                                      than in_len, this function must return
+ *                                      an error other than TFM_PLAT_ERR_SUCCESS
+ *                                      and not write any OTP.
+ *
  * \retval TFM_PLAT_ERR_SUCCESS         The OTP is written successfully
  * \retval TFM_PLAT_ERR_UNSUPPORTED     The given element has not been
  *                                      instanciated in OTP memory by this