feat(console_log): add FFA_CONSOLE_LOG ABI
Add implementation-defined FFA_CONSOLE_LOG_32/64 ABIs.
Input parameters:
w0/x0 - FFA_CONSOLE_LOG_32/64
w1/x1 - Character count
w2/x2-w7/x7 - 24 or 48 characters depending upon whether a SMC32 or
SMC64 FID was used.
Output parameters in case of success:
w0/x0 - FFA_SUCCESS
Output parameters in case of error:
w0/x0 - FFA_ERROR
w2/x2 - NOT_SUPPORTED: ABI is not implemented
INVALID_PARAMETERS: Parameters are incorrectly encoded
Signed-off-by: Maksims Svecovs <maksims.svecovs@arm.com>
Change-Id: Ic38d354d736cc7691010ab6d7dbcc42a69ef7c61
diff --git a/src/api.c b/src/api.c
index 7424b24..20bdd17 100644
--- a/src/api.c
+++ b/src/api.c
@@ -3562,3 +3562,79 @@
return ret;
}
+
+/**
+ * Helper function for FFA_CONSOLE_LOG ABI.
+ * Writes number of characters to a given VM buffer.
+ */
+static rsize_t arg_to_char_helper(struct vm_locked from_locked,
+ const uint64_t src, rsize_t src_size,
+ rsize_t to_write)
+{
+ bool flush = false;
+ char c;
+ rsize_t size = src_size < to_write ? src_size : to_write;
+ rsize_t written = 0;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ while (written < size) {
+ c = ((char *)&src)[written++];
+ if (c == '\n' || c == '\0') {
+ flush = true;
+ } else {
+ from_locked.vm->log_buffer
+ [from_locked.vm->log_buffer_length++] = c;
+ flush = (from_locked.vm->log_buffer_length ==
+ LOG_BUFFER_SIZE);
+ }
+
+ if (flush) {
+ dlog_flush_vm_buffer(from_locked.vm->id,
+ from_locked.vm->log_buffer,
+ from_locked.vm->log_buffer_length);
+ from_locked.vm->log_buffer_length = 0;
+ }
+ }
+
+ return written;
+}
+
+/**
+ * Implements FFA_CONSOLE_LOG buffered logging.
+ */
+struct ffa_value api_ffa_console_log(const struct ffa_value args,
+ struct vcpu *current)
+{
+ struct vm *vm = current->vm;
+ struct vm_locked vm_locked;
+ size_t chars_in_param = args.func == FFA_CONSOLE_LOG_32
+ ? sizeof(uint32_t)
+ : sizeof(uint64_t);
+ size_t total_to_write = args.arg1;
+
+ if (total_to_write == 0 || total_to_write > chars_in_param * 6) {
+ return ffa_error(FFA_INVALID_PARAMETERS);
+ }
+
+ vm_locked = vm_lock(vm);
+
+ total_to_write -= arg_to_char_helper(vm_locked, args.arg2,
+ chars_in_param, total_to_write);
+ total_to_write -= arg_to_char_helper(vm_locked, args.arg3,
+ chars_in_param, total_to_write);
+ total_to_write -= arg_to_char_helper(vm_locked, args.arg4,
+ chars_in_param, total_to_write);
+ total_to_write -= arg_to_char_helper(vm_locked, args.arg5,
+ chars_in_param, total_to_write);
+ total_to_write -= arg_to_char_helper(vm_locked, args.arg6,
+ chars_in_param, total_to_write);
+ arg_to_char_helper(vm_locked, args.arg7, chars_in_param,
+ total_to_write);
+
+ vm_unlock(&vm_locked);
+
+ return (struct ffa_value){.func = FFA_SUCCESS_32};
+}