refactor: add explicit underlying types to enums

* Set the underlying type of `ffa_error` to `uint32_t`. This reduces the
  need for explicit casts in most cases.
* Set the underlying types for other enums to `uint32_t`, where they are
  specified as such in the FF-A specification (`ffa_version`,
  `ffa_feature_id`, `ffa_mem_perm`, `ffa_framework_msg_func`).
* Set the underlying types of `ffa_data_access`,
  `ffa_instruction_access`, `ffa_memory_type`,
  `ffa_memory_cacheability`, `ffa_memory_shareability`,
  `ffa_memory_security` to `uint8_t`. This allows them to be stored
  directly in the `ffa_data_access_t` and `ffa_memory_attributes_t`
  structs without increasing their size.

Change-Id: I7da103f7507929ffb2e66914daa3cd9e67186300
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index eca1a51..240de5e 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -17,7 +17,7 @@
  *
  * See FF-A specification v1.2 ALP1, section 13.2.1.
  */
-enum ffa_version {
+enum ffa_version : uint32_t {
 	FFA_VERSION_1_0 = 0x10000,
 	FFA_VERSION_1_1 = 0x10001,
 	FFA_VERSION_1_2 = 0x10002,
@@ -155,18 +155,24 @@
 /**
  * FF-A error codes.
  * Don't forget to update `ffa_error_name` if you add a new one.
+ *
+ * NOTE: Error codes have negative values, but we set the underlying type of the
+ * enum to `uint32_t` because it is more convenient to treat them as unsigned
+ * values: the SMCC calling convention specifies that signed 32 bit values must
+ * be zero-extended when passed in 64-bit registers (ie the upper 32 bits must
+ * be zero).
  */
-enum ffa_error {
-	FFA_NOT_SUPPORTED      = -1,
-	FFA_INVALID_PARAMETERS = -2,
-	FFA_NO_MEMORY          = -3,
-	FFA_BUSY               = -4,
-	FFA_INTERRUPTED        = -5,
-	FFA_DENIED             = -6,
-	FFA_RETRY              = -7,
-	FFA_ABORTED            = -8,
-	FFA_NO_DATA            = -9,
-	FFA_NOT_READY          = -10,
+enum ffa_error : uint32_t {
+	FFA_NOT_SUPPORTED      = UINT32_C(-1),
+	FFA_INVALID_PARAMETERS = UINT32_C(-2),
+	FFA_NO_MEMORY          = UINT32_C(-3),
+	FFA_BUSY               = UINT32_C(-4),
+	FFA_INTERRUPTED        = UINT32_C(-5),
+	FFA_DENIED             = UINT32_C(-6),
+	FFA_RETRY              = UINT32_C(-7),
+	FFA_ABORTED            = UINT32_C(-8),
+	FFA_NO_DATA            = UINT32_C(-9),
+	FFA_NOT_READY          = UINT32_C(-10),
 };
 
 /* clang-format on */
@@ -341,7 +347,7 @@
 #define FFA_FEATURES_MEM_RETRIEVE_REQ_MBZ_LO_BIT (2U)
 #define FFA_FEATURES_MEM_RETRIEVE_REQ_MBZ_BIT (0U)
 
-enum ffa_feature_id {
+enum ffa_feature_id : uint32_t {
 	/* Query interrupt ID of Notification Pending Interrupt. */
 	FFA_FEATURE_NPI = 1,
 
@@ -374,7 +380,7 @@
  * The type of memory permissions used by `FFA_MEM_PERM_GET` and
  * `FFA_MEM_PERM_SET`.
  */
-enum ffa_mem_perm {
+enum ffa_mem_perm : uint32_t {
 	FFA_MEM_PERM_RO = 0x7,
 	FFA_MEM_PERM_RW = 0x5,
 	FFA_MEM_PERM_RX = 0x3,
@@ -592,7 +598,7 @@
 /* The maximum length possible for a single message. */
 #define FFA_MSG_PAYLOAD_MAX HF_MAILBOX_SIZE
 
-enum ffa_data_access {
+enum ffa_data_access : uint8_t {
 	FFA_DATA_ACCESS_NOT_SPECIFIED,
 	FFA_DATA_ACCESS_RO,
 	FFA_DATA_ACCESS_RW,
@@ -613,7 +619,7 @@
 	}
 }
 
-enum ffa_instruction_access {
+enum ffa_instruction_access : uint8_t {
 	FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
 	FFA_INSTRUCTION_ACCESS_NX,
 	FFA_INSTRUCTION_ACCESS_X,
@@ -635,7 +641,7 @@
 	}
 }
 
-enum ffa_memory_type {
+enum ffa_memory_type : uint8_t {
 	FFA_MEMORY_NOT_SPECIFIED_MEM,
 	FFA_MEMORY_DEVICE_MEM,
 	FFA_MEMORY_NORMAL_MEM,
@@ -653,7 +659,7 @@
 	}
 }
 
-enum ffa_memory_cacheability {
+enum ffa_memory_cacheability : uint8_t {
 	FFA_MEMORY_CACHE_RESERVED = 0x0,
 	FFA_MEMORY_CACHE_NON_CACHEABLE = 0x1,
 	FFA_MEMORY_CACHE_RESERVED_1 = 0x2,
@@ -694,7 +700,7 @@
 	}
 }
 
-enum ffa_memory_shareability {
+enum ffa_memory_shareability : uint8_t {
 	FFA_MEMORY_SHARE_NON_SHAREABLE,
 	FFA_MEMORY_SHARE_RESERVED,
 	FFA_MEMORY_OUTER_SHAREABLE,
@@ -721,7 +727,7 @@
  * Per section 10.10.4.1, NS bit is reserved for FFA_MEM_DONATE/LEND/SHARE
  * and FFA_MEM_RETRIEVE_REQUEST.
  */
-enum ffa_memory_security {
+enum ffa_memory_security : uint8_t {
 	FFA_MEMORY_SECURITY_UNSPECIFIED = 0,
 	FFA_MEMORY_SECURITY_SECURE = 0,
 	FFA_MEMORY_SECURITY_NON_SECURE,
@@ -739,22 +745,28 @@
 }
 
 typedef struct {
-	uint8_t data_access : 2;
-	uint8_t instruction_access : 2;
+	enum ffa_data_access data_access : 2;
+	enum ffa_instruction_access instruction_access : 2;
 } ffa_memory_access_permissions_t;
 
+static_assert(sizeof(ffa_memory_access_permissions_t) == sizeof(uint8_t),
+	      "ffa_memory_access_permissions_t must be 8 bits wide");
+
 /**
  * This corresponds to table 10.18 of the FF-A v1.1 EAC0 specification, "Memory
  * region attributes descriptor".
  */
 typedef struct {
-	uint8_t shareability : 2;
-	uint8_t cacheability : 2;
-	uint8_t type : 2;
-	uint8_t security : 2;
+	enum ffa_memory_shareability shareability : 2;
+	enum ffa_memory_cacheability cacheability : 2;
+	enum ffa_memory_type type : 2;
+	enum ffa_memory_security security : 2;
 	uint8_t : 8;
 } ffa_memory_attributes_t;
 
+static_assert(sizeof(ffa_memory_attributes_t) == sizeof(uint16_t),
+	      "ffa_memory_attributes_t must be 16 bits wide");
+
 /* FF-A v1.1 EAC0 states bit [15:7] Must Be Zero. */
 #define FFA_MEMORY_ATTRIBUTES_MBZ_MASK 0xFF80U
 
@@ -947,7 +959,7 @@
  * Identifies FF-A framework messages. See sections 18.2 and 18.3 of v1.2 FF-A
  * specification.
  */
-enum ffa_framework_msg_func {
+enum ffa_framework_msg_func : uint32_t {
 	/* Power management framework messages. */
 	FFA_FRAMEWORK_MSG_PSCI_REQ = 0,
 	FFA_FRAMEWORK_MSG_PSCI_RESP = 2,
diff --git a/src/api.c b/src/api.c
index ebb6561..9a183a8 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2408,7 +2408,7 @@
 	static_assert(sizeof(enum ffa_version) == 4,
 		      "enum ffa_version must be 4 bytes wide");
 
-	const struct ffa_value error = {.func = (uint32_t)FFA_NOT_SUPPORTED};
+	const struct ffa_value error = {.func = FFA_NOT_SUPPORTED};
 	struct vm_locked current_vm_locked;
 
 	uint16_t compiled_major = ffa_version_get_major(FFA_VERSION_COMPILED);
@@ -2456,7 +2456,7 @@
 	current_vm_locked.vm->ffa_version = requested_version;
 	vm_unlock(&current_vm_locked);
 
-	return (struct ffa_value){.func = (uint32_t)FFA_VERSION_COMPILED};
+	return (struct ffa_value){.func = FFA_VERSION_COMPILED};
 }
 
 /**
diff --git a/src/arch/aarch64/hftest/power_mgmt.c b/src/arch/aarch64/hftest/power_mgmt.c
index 68a2c33..aefa120 100644
--- a/src/arch/aarch64/hftest/power_mgmt.c
+++ b/src/arch/aarch64/hftest/power_mgmt.c
@@ -46,6 +46,7 @@
 	}
 }
 
+/* NOLINTBEGIN(readability-redundant-casting) */
 static_assert((uint32_t)POWER_STATUS_ON == (uint32_t)PSCI_RETURN_ON,
 	      "power_status enum values must match PSCI return values.");
 static_assert((uint32_t)POWER_STATUS_OFF == (uint32_t)PSCI_RETURN_OFF,
@@ -53,6 +54,7 @@
 static_assert((uint32_t)POWER_STATUS_ON_PENDING ==
 		      (uint32_t)PSCI_RETURN_ON_PENDING,
 	      "power_status enum values must match PSCI return values.");
+/* NOLINTEND(readability-redundant-casting) */
 
 /**
  * Returns the power status of the given CPU.
diff --git a/src/arch/aarch64/inc/hf/arch/vm/power_mgmt.h b/src/arch/aarch64/inc/hf/arch/vm/power_mgmt.h
index 7bf8d4b..e41edf6 100644
--- a/src/arch/aarch64/inc/hf/arch/vm/power_mgmt.h
+++ b/src/arch/aarch64/inc/hf/arch/vm/power_mgmt.h
@@ -13,7 +13,7 @@
 
 #include "hf/arch/types.h"
 
-enum power_status {
+enum power_status : uint32_t {
 	POWER_STATUS_ON,
 	POWER_STATUS_OFF,
 	POWER_STATUS_ON_PENDING,
diff --git a/src/arch/aarch64/psci.h b/src/arch/aarch64/psci.h
index 55fc17d..c90ec94 100644
--- a/src/arch/aarch64/psci.h
+++ b/src/arch/aarch64/psci.h
@@ -13,7 +13,7 @@
 /* clang-format off */
 
 /* The following are PSCI version codes. */
-enum psci_version {
+enum psci_version : uint32_t {
 	PSCI_VERSION_0_2 = 0x00000002,
 	PSCI_VERSION_1_0 = 0x00010000,
 	PSCI_VERSION_1_1 = 0x00010001,
@@ -43,7 +43,7 @@
 #define PSCI_MEM_PROTECT_CHECK_RANGE 0x84000014
 
 /* The following are return codes for PSCI. */
-enum psci_return_code {
+enum psci_return_code : uint32_t {
 	PSCI_RETURN_ON_PENDING         = 2,
 	PSCI_RETURN_OFF                = 1,
 	PSCI_RETURN_ON                 = 0,
diff --git a/src/ffa/hypervisor/init.c b/src/ffa/hypervisor/init.c
index b87ca54..f9c98e8 100644
--- a/src/ffa/hypervisor/init.c
+++ b/src/ffa/hypervisor/init.c
@@ -66,7 +66,7 @@
 	 */
 	ret = arch_other_world_call((struct ffa_value){
 		.func = FFA_VERSION_32, .arg1 = FFA_VERSION_COMPILED});
-	if (ret.func == (uint32_t)FFA_NOT_SUPPORTED) {
+	if (ret.func == FFA_NOT_SUPPORTED) {
 		panic("Hypervisor and SPMC versions are not compatible.\n");
 	}
 
diff --git a/test/vmapi/ffa_secure_partitions/notifications.c b/test/vmapi/ffa_secure_partitions/notifications.c
index 47a8f8e..93f9b96 100644
--- a/test/vmapi/ffa_secure_partitions/notifications.c
+++ b/test/vmapi/ffa_secure_partitions/notifications.c
@@ -241,7 +241,7 @@
 				    FFA_NOTIFICATION_MASK(1));
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(sp_resp(res), SP_ERROR);
-	EXPECT_EQ((int32_t)sp_resp_value(res), FFA_INVALID_PARAMETERS);
+	EXPECT_EQ(sp_resp_value(res), FFA_INVALID_PARAMETERS);
 }
 
 /**
@@ -265,7 +265,7 @@
 				    FFA_NOTIFICATION_MASK(1));
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(sp_resp(res), SP_ERROR);
-	EXPECT_EQ((int32_t)sp_resp_value(res), FFA_INVALID_PARAMETERS);
+	EXPECT_EQ(sp_resp_value(res), FFA_INVALID_PARAMETERS);
 }
 
 TEST(ffa_notifications, fail_if_global_notif_set_as_per_vcpu)
@@ -285,7 +285,7 @@
 				    FFA_NOTIFICATION_MASK(1));
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(sp_resp(res), SP_ERROR);
-	EXPECT_EQ((int32_t)sp_resp_value(res), FFA_INVALID_PARAMETERS);
+	EXPECT_EQ(sp_resp_value(res), FFA_INVALID_PARAMETERS);
 }
 
 TEST(ffa_notifications, fail_if_per_vcpu_notif_set_as_global)
@@ -305,7 +305,7 @@
 				    FFA_NOTIFICATION_MASK(1));
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(sp_resp(res), SP_ERROR);
-	EXPECT_EQ((int32_t)sp_resp_value(res), FFA_INVALID_PARAMETERS);
+	EXPECT_EQ(sp_resp_value(res), FFA_INVALID_PARAMETERS);
 }
 
 TEST(ffa_notifications, fail_if_mbz_set_in_notifications_bind)
diff --git a/test/vmapi/ffa_secure_partitions/setup_and_discovery.c b/test/vmapi/ffa_secure_partitions/setup_and_discovery.c
index e68079a..1d5f18f 100644
--- a/test/vmapi/ffa_secure_partitions/setup_and_discovery.c
+++ b/test/vmapi/ffa_secure_partitions/setup_and_discovery.c
@@ -363,7 +363,7 @@
 	res = sp_ffa_features_cmd_send(own_id, receiver_id, FFA_FEATURE_NPI);
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(res.arg3, FFA_ERROR_32);
-	EXPECT_EQ((int32_t)res.arg4, FFA_NOT_SUPPORTED);
+	EXPECT_EQ(res.arg4, FFA_NOT_SUPPORTED);
 }
 
 TEST_PRECONDITION(ffa, secondary_ep_register_supported, service2_is_mp_sp)
@@ -390,5 +390,5 @@
 				       FFA_SECONDARY_EP_REGISTER_64);
 	EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
 	EXPECT_EQ(res.arg3, FFA_ERROR_32);
-	EXPECT_EQ((int32_t)res.arg4, FFA_NOT_SUPPORTED);
+	EXPECT_EQ(res.arg4, FFA_NOT_SUPPORTED);
 }
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 70f50e4..7edcb6b 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -185,19 +185,17 @@
 	EXPECT_EQ(ffa_version(current_version), current_version);
 	EXPECT_EQ(ffa_version(older_compatible_version_0), current_version);
 	EXPECT_EQ(ffa_version(older_compatible_version_1), current_version);
-	EXPECT_EQ((int32_t)ffa_version(0x0), FFA_NOT_SUPPORTED);
-	EXPECT_EQ((int32_t)ffa_version(0x1), FFA_NOT_SUPPORTED);
-	EXPECT_EQ((int32_t)ffa_version(0x10003), FFA_NOT_SUPPORTED);
-	EXPECT_EQ((int32_t)ffa_version(0xffff), FFA_NOT_SUPPORTED);
-	EXPECT_EQ((int32_t)ffa_version(0xfffffff), FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0x0), FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0x1), FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0x10003), FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0xffff), FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0xfffffff), FFA_NOT_SUPPORTED);
 }
 
 /** Ensures that an invalid call to FFA_VERSION gets an error back. */
 TEST(ffa, ffa_version_invalid)
 {
-	int32_t ret = (int32_t)ffa_version(0x80000000);
-
-	EXPECT_EQ(ret, FFA_NOT_SUPPORTED);
+	EXPECT_EQ(ffa_version(0x80000000), FFA_NOT_SUPPORTED);
 }
 
 static bool v1_0_or_later(void)
diff --git a/test/vmapi/primary_with_secondaries/dir_msg.c b/test/vmapi/primary_with_secondaries/dir_msg.c
index 5273ae3..f134548 100644
--- a/test/vmapi/primary_with_secondaries/dir_msg.c
+++ b/test/vmapi/primary_with_secondaries/dir_msg.c
@@ -1178,9 +1178,9 @@
 	ffa_id_t sender_id, ffa_id_t receiver_id, ffa_id_t vm_id,
 	enum ffa_framework_msg_func framework_func)
 {
-	assert_vm_availability_message(sender_id, receiver_id, vm_id,
-				       framework_func, FFA_ERROR_32, 0, 0,
-				       FFA_INVALID_PARAMETERS, 0);
+	assert_vm_availability_message(
+		sender_id, receiver_id, vm_id, framework_func, FFA_ERROR_32, 0,
+		0, (enum ffa_framework_msg_func)FFA_INVALID_PARAMETERS, 0);
 }
 
 /**