Browse Source

print: Allow for more than one output for console messages

Aaron Lindsay 7 years ago
parent
commit
5f59e07432
3 changed files with 74 additions and 13 deletions
  1. 3 1
      include/print.h
  2. 69 11
      kernel/print.c
  3. 2 1
      kernel/start_kernel.c

+ 3 - 1
include/print.h

@@ -21,7 +21,9 @@
21 21
 #ifndef PRINT_H
22 22
 #define PRINT_H
23 23
 
24
-void print_init(int (*putc)(char));
24
+int print_register_func_early(int (*putc)(char));
25
+int print_register_func(int (*putc)(char));
26
+int print_unregister_func(int (*putc)(char));
25 27
 int print(char *fmt, ...);
26 28
 int print_func(int (putcf)(char), char *fmt, ...);
27 29
 

+ 69 - 11
kernel/print.c

@@ -18,25 +18,77 @@
18 18
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 19
  */
20 20
 
21
+#include <init.h>
22
+#include <list.h>
23
+#include <kmalloc.h>
21 24
 #include <print.h>
22 25
 #include <vargs.h>
23 26
 
24
-/* This function exists solely so crashes don't happen if putc() gets
25
- * called before it is initialized. */
26
-int putc_initial(char c) {
27
-	(void)c;
27
+struct dlist_node print_funcs_list;
28
+
29
+struct print_func {
30
+	int (*putc)(char);
31
+	struct dlist_node list;
32
+};
33
+
34
+/*
35
+ * On startup, we'd like to have print capabilities before kmalloc is
36
+ * initialized, so statically allocate one struct print_func to allow for the
37
+ * registration of one print 'sink' before kmalloc is initialized.
38
+ */
39
+struct print_func print_func_early;
40
+int print_register_func_early(int (*putc)(char)) {
41
+	if (list_empty(&print_funcs_list)) {
42
+		print_func_early.putc = putc;
43
+		insert_before(&print_funcs_list, &print_func_early.list);
44
+		return 0;
45
+	}
46
+	return -1;
47
+}
48
+
49
+int print_register_func(int (*putc)(char)) {
50
+	struct print_func *pf;
51
+	if (!(pf = kmalloc(sizeof(struct print_func))))
52
+		return -1;
53
+
54
+	pf->putc = putc;
55
+	insert_before(&print_funcs_list, &pf->list);
28 56
 	return 0;
29 57
 }
30
-int (*print_putc)(char) = &putc_initial;
31 58
 
32
-void print_init(int (*putcfn)(char)) {
33
-	if (putcfn)
34
-		print_putc = putcfn;
59
+int print_unregister_func(int (*putc)(char)) {
60
+	struct print_func *it;
61
+
62
+	if (list_empty(&print_funcs_list))
63
+		return -1;
64
+
65
+	for_each_list(it, &print_funcs_list, struct print_func, list) {
66
+		if (it->putc == putc) {
67
+			remove(&it->list);
68
+
69
+			//only kfree if it was kmalloced
70
+			if (it != &print_func_early)
71
+				kfree(it);
72
+			return 0;
73
+		}
74
+	}
75
+	return -1;
76
+}
77
+
78
+int print_putc(char c) {
79
+	struct print_func *it;
80
+
81
+	if (list_empty(&print_funcs_list))
82
+		return -1;
83
+
84
+	for_each_list(it, &print_funcs_list, struct print_func, list)
85
+		it->putc(c);
86
+	return 0;
35 87
 }
36
- 
88
+
37 89
 void puts(int (*putc)(char), const char *s)
38 90
 {
39
-    while (*s) putc (*s++);
91
+	while (*s) putc(*s++);
40 92
 }
41 93
 
42 94
 void puti(int (*putc)(char), int i)
@@ -132,7 +184,7 @@ int print(char *fmt, ...) {
132 184
 	va_list arg;
133 185
 
134 186
 	va_start(arg, fmt);
135
-	ret = _print(print_putc, fmt, arg);
187
+	ret = _print(&print_putc, fmt, arg);
136 188
 	va_end(arg);
137 189
 
138 190
 	return ret;
@@ -149,3 +201,9 @@ int print_func(int (*putc)(char), char *fmt, ...) {
149 201
 
150 202
 	return ret;
151 203
 }
204
+
205
+void print_init() {
206
+	init_list(&print_funcs_list);
207
+}
208
+
209
+early_initcall(print_init);

+ 2 - 1
kernel/start_kernel.c

@@ -59,6 +59,7 @@ void video_console_init(void) {
59 59
 	if ((console_init(&console_fb)))
60 60
 		return;
61 61
 
62
+	print_register_func(&console_putc);
62 63
 	print_console_logo();
63 64
 
64 65
 	print_func(&console_putc, "Successfully initialized video console on %s.\n", fbdev->name);
@@ -70,7 +71,7 @@ void serial_console_init() {
70 71
 	if (!sdev)
71 72
 		return;
72 73
 
73
-	print_init(sdev->putc);
74
+	print_register_func_early(sdev->putc);
74 75
 	print("Successfully initialized serial console on %s\n", sdev->name);
75 76
 }
76 77