Keep logs in a circular buffer so they can be extracted from a RAM dump.
Bug: 115484857, 132429213
Change-Id: I7ae3fd6c24ca8b42f581d9d4417fc6c49b23b43d
diff --git a/inc/hf/dlog.h b/inc/hf/dlog.h
index f36c428..f8c0080 100644
--- a/inc/hf/dlog.h
+++ b/inc/hf/dlog.h
@@ -21,6 +21,11 @@
#include "hf/spci.h"
+#define DLOG_BUFFER_SIZE 8192
+
+extern size_t dlog_buffer_offset;
+extern char dlog_buffer[];
+
#if DEBUG
void dlog_enable_lock(void);
void dlog(const char *fmt, ...);
diff --git a/src/dlog.c b/src/dlog.c
index 1b0a793..1bda568 100644
--- a/src/dlog.c
+++ b/src/dlog.c
@@ -42,6 +42,13 @@
static bool dlog_lock_enabled = false;
static struct spinlock sl = SPINLOCK_INIT;
+/*
+ * These global variables for the log buffer are not static because a test needs
+ * to access them directly.
+ */
+size_t dlog_buffer_offset;
+char dlog_buffer[DLOG_BUFFER_SIZE];
+
/**
* Takes the lock, if it is enabled.
*/
@@ -70,6 +77,13 @@
dlog_lock_enabled = true;
}
+static void dlog_putchar(char c)
+{
+ dlog_buffer[dlog_buffer_offset] = c;
+ dlog_buffer_offset = (dlog_buffer_offset + 1) % DLOG_BUFFER_SIZE;
+ plat_console_putchar(c);
+}
+
/**
* Prints a raw string to the debug log and returns its length.
*/
@@ -78,7 +92,7 @@
const char *c = str;
while (*c != '\0') {
- plat_console_putchar(*c++);
+ dlog_putchar(*c++);
}
return c - str;
@@ -100,14 +114,14 @@
/* Print the string up to the beginning of the suffix. */
while (str != suffix) {
- plat_console_putchar(*str++);
+ dlog_putchar(*str++);
}
if (flags & FLAG_MINUS) {
/* Left-aligned. Print suffix, then print padding if needed. */
len += print_raw_string(suffix);
while (len < width) {
- plat_console_putchar(' ');
+ dlog_putchar(' ');
len++;
}
return;
@@ -116,7 +130,7 @@
/* Fill until we reach the desired length. */
len += strnlen_s(suffix, DLOG_MAX_STRING_LENGTH);
while (len < width) {
- plat_console_putchar(fill);
+ dlog_putchar(fill);
len++;
}
@@ -224,10 +238,10 @@
print_raw_string(": ");
for (size_t i = 0; i < length; ++i) {
- plat_console_putchar(buffer[i]);
+ dlog_putchar(buffer[i]);
buffer[i] = '\0';
}
- plat_console_putchar('\n');
+ dlog_putchar('\n');
unlock();
}
@@ -247,7 +261,7 @@
for (p = fmt; *p; p++) {
switch (*p) {
default:
- plat_console_putchar(*p);
+ dlog_putchar(*p);
break;
case '%':
@@ -335,7 +349,7 @@
break;
default:
- plat_console_putchar('%');
+ dlog_putchar('%');
}
break;
diff --git a/test/arch/BUILD.gn b/test/arch/BUILD.gn
index d99a667..c770dee 100644
--- a/test/arch/BUILD.gn
+++ b/test/arch/BUILD.gn
@@ -27,6 +27,7 @@
testonly = true
sources = [
+ "dlog_test.c",
"mm_test.c",
]
diff --git a/test/arch/dlog_test.c b/test/arch/dlog_test.c
new file mode 100644
index 0000000..49403e1
--- /dev/null
+++ b/test/arch/dlog_test.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/dlog.h"
+
+#include "hftest.h"
+
+/**
+ * Test that logs are written to the buffer, and the rest is empty.
+ */
+TEST(dlog, log_buffer)
+{
+ const char test_string[] = "Test string\n";
+
+ dlog(test_string);
+ ASSERT_EQ(strcmp(test_string, dlog_buffer), 0);
+ /* The \0 at the end shouldn't be counted. */
+ ASSERT_EQ(dlog_buffer_offset, sizeof(test_string) - 1);
+ for (int i = sizeof(test_string) - 1; i < DLOG_BUFFER_SIZE; ++i) {
+ EXPECT_EQ(dlog_buffer[i], '\0');
+ }
+}