psa_sim_serialise.pl now creates the updated .c file

Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
index e45cd00..348e42c 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -85,6 +85,7 @@
     return -1;  /* all in use */
 }
 
+/* Find the slot given the handle */
 static ssize_t find_hash_slot_by_handle(psasim_client_handle_t handle)
 {
     for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
@@ -450,10 +451,6 @@
     return 1;
 }
 
-/* On the server side, we have a certain number of slots. One array holds the
- * psa_XXX_operation_t values by slot, the other holds the client-side handles
- * for the slots.
- */
 size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation)
 {
     (void) operation;
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
index 21bfec5..eb2893e 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -69,7 +69,17 @@
 
 } elsif ($which eq "c") {
 
+    my $have_operation_types = (grep(/psa_\w+_operation_t/, @types)) ? 1 : 0;
+
     print c_header();
+    print c_define_types_for_operation_types() if $have_operation_types;
+
+    for my $type (@types) {
+        next unless $type =~ /^psa_(\w+)_operation_t$/;
+        print define_operation_type_data_and_functions($1);
+    }
+
+    print c_define_begins();
 
     for my $type (@types) {
         if ($type eq "buffer") {
@@ -82,6 +92,12 @@
             print define_needs($type);
             print define_serialise($type);
             print define_deserialise($type);
+
+            if ($type =~ /^psa_\w+_operation_t$/) {
+                print define_server_needs($type);
+                print define_server_serialise($type);
+                print define_server_deserialise($type);
+            }
         }
     }
 
@@ -363,6 +379,25 @@
 EOF
 }
 
+sub define_server_needs
+{
+    my ($type) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return <<EOF;
+
+size_t psasim_server_serialise_${type_d}_needs($type *operation)
+{
+    (void) operation;
+
+    /* We will actually return a handle */
+    return sizeof(psasim_operation_t);
+}
+EOF
+}
+
 sub define_needs_isa
 {
     my ($type, $isa) = @_;
@@ -407,6 +442,44 @@
 EOF
 }
 
+sub define_server_serialise
+{
+    my ($type) = @_;
+
+    my $t;
+    if ($type =~ /^psa_(\w+)_operation_t$/) {
+        $t = $1;
+    } else {
+        die("$0: define_server_serialise: $type: not supported\n");
+    }
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_server_serialise_$type_d(uint8_t **pos,
+                             size_t *remaining,
+                             $type *operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(client_operation)) {
+        return 0;
+    }
+
+    ssize_t slot = operation - ${t}_operations;
+
+    client_operation.handle = ${t}_operation_handles[slot];
+
+    memcpy(*pos, &client_operation, sizeof(client_operation));
+    *pos += sizeof(client_operation);
+
+    return 1;
+}
+EOF
+}
+
 sub define_serialise_isa
 {
     my ($type, $isa) = @_;
@@ -455,6 +528,54 @@
 EOF
 }
 
+sub define_server_deserialise
+{
+    my ($type) = @_;
+
+    my $t;
+    if ($type =~ /^psa_(\w+)_operation_t$/) {
+        $t = $1;
+    } else {
+        die("$0: define_server_serialise: $type: not supported\n");
+    }
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_server_deserialise_$type_d(uint8_t **pos,
+                               size_t *remaining,
+                               $type **operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(psasim_operation_t)) {
+        return 0;
+    }
+
+    memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
+    *pos += sizeof(psasim_operation_t);
+    *remaining -= sizeof(psasim_operation_t);
+
+    ssize_t slot;
+    if (client_operation.handle == 0) {         /* We need a new handle */
+        slot = allocate_${t}_operation_slot();
+    } else {
+        slot = find_${t}_slot_by_handle(client_operation.handle);
+    }
+
+    if (slot < 0) {
+        return 0;
+    }
+
+    *operation = &${t}_operations[slot];
+
+    return 1;
+}
+EOF
+}
+
 sub define_deserialise_isa
 {
     my ($type, $isa) = @_;
@@ -639,6 +760,72 @@
  * data types (e.g. int), types typedef'd to those, and even structures that
  * don't contain pointers.
  */
+EOF
+}
+
+sub c_define_types_for_operation_types
+{
+    return <<'EOF';
+
+/* include/psa/crypto_platform.h:typedef uint32_t mbedtls_psa_client_handle_t;
+ * but we don't get it on server builds, so redefine it here with a unique type name
+ */
+typedef uint32_t psasim_client_handle_t;
+
+typedef struct psasim_operation_s {
+    psasim_client_handle_t handle;
+} psasim_operation_t;
+
+#define MAX_LIVE_HANDLES_PER_CLASS   100        /* this many slots */
+EOF
+}
+
+sub define_operation_type_data_and_functions
+{
+    my ($type) = @_;    # e.g. 'hash' rather than 'psa_hash_operation_t'
+
+    return <<EOF;
+
+static psa_${type}_operation_t ${type}_operations[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t ${type}_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_${type}_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_${type}_operation_slot(void)
+{
+    psasim_client_handle_t handle = next_${type}_operation_handle++;
+    if (next_${type}_operation_handle == 0) {      /* wrapped around */
+        fprintf(stderr, "MAX HASH HANDLES REACHED\\n");
+        exit(1);
+    }
+
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (${type}_operation_handles[i] == 0) {
+            ${type}_operation_handles[i] = handle;
+            return i;
+        }
+    }
+
+    return -1;  /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_${type}_slot_by_handle(psasim_client_handle_t handle)
+{
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (${type}_operation_handles[i] == handle) {
+            return i;
+        }
+    }
+
+    return -1;  /* all in use */
+}
+EOF
+}
+
+sub c_define_begins
+{
+    return <<'EOF';
 
 size_t psasim_serialise_begin_needs(void)
 {