feat(dlog): adopt FF-A in `stdout_putchar`

Use the extended FFA_CONSOLE_LOG64 ABI in `stdout_putchar` when it is
available.

Change-Id: I66405a7082b8af484d6829c9f6cea9209e3b66ae
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/inc/hf/stdout.h b/inc/hf/stdout.h
index 73b667d..2405057 100644
--- a/inc/hf/stdout.h
+++ b/inc/hf/stdout.h
@@ -8,10 +8,13 @@
 
 #pragma once
 
+#include <stdint.h>
+
 /**
  * Print one character to standard output.
  * This is intentionally called differently from functions in <stdio.h> so as to
  * avoid clashes when linking against libc.
  */
+void stdout_init(uint32_t ffa_version);
 void stdout_putchar(char c);
 void stdout_flush(void);
diff --git a/src/arch/aarch64/hftest/stdout.c b/src/arch/aarch64/hftest/stdout.c
index 4632e4e..059afd0 100644
--- a/src/arch/aarch64/hftest/stdout.c
+++ b/src/arch/aarch64/hftest/stdout.c
@@ -6,40 +6,74 @@
  * https://opensource.org/licenses/BSD-3-Clause.
  */
 
-#include "hf/stdout.h"
-
 #include "hf/assert.h"
+#include "hf/ffa.h"
+#include "hf/std.h"
 
 #include "vmapi/hf/call.h"
 
-#define FFA_CONSOLE_LOG64_MAX_CHAR ((size_t)48)
+#define CHARS_PER_REG UINT32_C(8)
+#define REGS_PER_CALL UINT32_C(6)
+#define REGS_PER_EXTENDED_CALL UINT32_C(16)
+#define MAX_CHARS (CHARS_PER_REG * REGS_PER_CALL)
+#define MAX_CHARS_EXTENDED (CHARS_PER_REG * REGS_PER_EXTENDED_CALL)
 
-static char stdout_buffer[FFA_CONSOLE_LOG64_MAX_CHAR];
-static size_t buffer_char_count = 0;
+struct stdout_buffer {
+	char chars[MAX_CHARS_EXTENDED];
+	size_t len;
+	bool extended;
+};
+
+static struct stdout_buffer buffers[1] = {{
+	.chars = {0},
+	.len = 0,
+	.extended = false,
+}};
+
+void stdout_init(uint32_t ffa_version)
+{
+	struct stdout_buffer *buffer = &buffers[0];
+
+	memset_s(buffer->chars, MAX_CHARS_EXTENDED, '\0', MAX_CHARS_EXTENDED);
+	buffer->extended = ffa_version >= FFA_VERSION_1_2;
+	buffer->len = 0;
+}
 
 void stdout_putchar(char c)
 {
-	/* Write single char to buffer. */
-	stdout_buffer[buffer_char_count++] = c;
+	struct ffa_value ret;
+	struct stdout_buffer *buffer = &buffers[0];
 
-	assert(buffer_char_count <= FFA_CONSOLE_LOG64_MAX_CHAR);
+	const size_t max_chars =
+		buffer->extended ? MAX_CHARS_EXTENDED : MAX_CHARS;
+
+	/* Write single char to buffer. */
+	buffer->chars[buffer->len++] = c;
+
+	assert(buffer->len <= max_chars);
+
 	/*
-	 * Flush buffer to stdout when buffer is full, a terminal character is
-	 * reached ('\0' or '\n'), or enough characters have been buffered to
-	 * fill all the registers in ffa_console_log_64.
+	 * Flush buffer to stdout when buffer is full, a terminal
+	 * character is reached ('\0' or '\n'), or enough characters
+	 * have been buffered to fill all the registers in (extended)
+	 * ffa_console_log_64.
 	 */
-	if (buffer_char_count == FFA_CONSOLE_LOG64_MAX_CHAR || c == '\0' ||
-	    c == '\n') {
-		ffa_console_log_64((const char *)stdout_buffer,
-				   buffer_char_count);
-		buffer_char_count = 0;
+	if (buffer->len == max_chars || c == '\0' || c == '\n') {
+		ret = buffer->extended
+			      ? ffa_console_log_64_extended(buffer->chars,
+							    buffer->len)
+			      : ffa_console_log_64(buffer->chars, buffer->len);
+		assert(ret.func == FFA_SUCCESS_32);
+		buffer->len = 0;
 	}
 }
 
 void stdout_flush(void)
 {
+	struct stdout_buffer *buffer = &buffers[0];
+
 	/* Skip flushing if buffer is empty. */
-	if (buffer_char_count > 0) {
+	if (buffer->len > 0) {
 		stdout_putchar('\0');
 	}
 }
diff --git a/test/hftest/service_common.c b/test/hftest/service_common.c
index d9b91d2..b277b38 100644
--- a/test/hftest/service_common.c
+++ b/test/hftest/service_common.c
@@ -12,6 +12,7 @@
 #include "hf/memiter.h"
 #include "hf/mm.h"
 #include "hf/std.h"
+#include "hf/stdout.h"
 
 #include "vmapi/hf/call.h"
 
@@ -116,6 +117,7 @@
 	ASSERT_TRUE(fdt_read_number(&root, "load-address",
 				    &ctx->partition_manifest.load_addr));
 	EXPECT_TRUE(fdt_read_number(&root, "ffa-version", &number));
+	ctx->partition_manifest.ffa_version = number;
 
 	EXPECT_TRUE(fdt_read_property(&root, "uuid", &uuid));
 
@@ -295,6 +297,7 @@
 		 * manifest for the SP.
 		 */
 		hftest_parse_ffa_manifest(ctx, &fdt);
+		stdout_init(ctx->partition_manifest.ffa_version);
 
 		/* TODO: Determine memory size referring to the SP Pkg. */
 		ctx->memory_size = 1048576;