blob: d931c65a127b65cd676ff97f2e644b6ad90b22e5 [file] [log] [blame]
Jeremy Kerr9326d772016-03-17 17:15:02 +08001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jeremy Kerr3f54de42016-03-09 18:10:15 +080016
17#include <endian.h>
18#include <err.h>
19#include <fcntl.h>
20#include <stdbool.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include <sys/mman.h>
27
28#include <linux/types.h>
29
30#include "console-server.h"
31
32struct log_handler {
33 struct handler handler;
34 struct console *console;
35 int fd;
36 size_t size;
37 size_t maxsize;
38 int pagesize;
39};
40
41
Jeremy Kerre440a402016-03-17 16:34:14 +080042static const char *default_filename = LOCALSTATEDIR "/log/obmc-console.log";
Jeremy Kerrdf94dc12016-03-16 12:19:49 +080043
Jeremy Kerr3f54de42016-03-09 18:10:15 +080044static const size_t logsize = 16 * 1024;
45
46static struct log_handler *to_log_handler(struct handler *handler)
47{
48 return container_of(handler, struct log_handler, handler);
49}
50
Jeremy Kerrd47963e2016-03-16 17:29:55 +080051static int log_init(struct handler *handler, struct console *console,
52 struct config *config __attribute__((unused)))
Jeremy Kerr3f54de42016-03-09 18:10:15 +080053{
54 struct log_handler *lh = to_log_handler(handler);
Jeremy Kerrb8f28452016-03-16 17:31:48 +080055 const char *filename;
Jeremy Kerr3f54de42016-03-09 18:10:15 +080056 int rc;
57
58 lh->console = console;
59 lh->maxsize = logsize;
60 lh->pagesize = 4096;
61 lh->size = 0;
62
Jeremy Kerrb8f28452016-03-16 17:31:48 +080063 filename = config_get_value(config, "logfile");
64 if (!filename)
65 filename = default_filename;
66
Jeremy Kerr3f54de42016-03-09 18:10:15 +080067 lh->fd = open(filename, O_RDWR | O_CREAT, 0644);
68 if (lh->fd < 0) {
69 warn("Can't open log buffer file %s", filename);
70 return -1;
71 }
72 rc = ftruncate(lh->fd, 0);
73 if (rc) {
74 warn("Can't truncate file %s", filename);
75 close(lh->fd);
76 return -1;
77 }
78
79 return 0;
80}
81
Jeremy Kerr3f54de42016-03-09 18:10:15 +080082static int log_trim(struct log_handler *lh, size_t space)
83{
84 int rc, n_shift_pages, shift_len, shift_start;
85 off_t pos;
86 void *buf;
87
88 pos = lseek(lh->fd, 0, SEEK_CUR);
89
90 n_shift_pages = (space + lh->pagesize - 1) / lh->pagesize;
91 shift_start = n_shift_pages * lh->pagesize;
92 shift_len = pos - (n_shift_pages * lh->pagesize);
93
94 buf = mmap(NULL, pos, PROT_READ | PROT_WRITE, MAP_SHARED, lh->fd, 0);
95 if (buf == MAP_FAILED)
96 return -1;
97
98 memmove(buf, buf + shift_start, shift_len);
99
100 munmap(buf, pos);
101
102 lh->size = shift_len;
103 rc = ftruncate(lh->fd, lh->size);
104 if (rc)
105 warn("failed to truncate file");
106 lseek(lh->fd, 0, SEEK_END);
107
108 return 0;
109
110}
111
112static int log_data(struct handler *handler, uint8_t *buf, size_t len)
113{
114 struct log_handler *lh = to_log_handler(handler);
115 int rc;
116
117 if (len > lh->maxsize) {
118 buf += len - lh->maxsize;
119 len = lh->maxsize;
120 }
121
122 if (lh->size + len > lh->maxsize) {
123 rc = log_trim(lh, len);
124 if (rc)
125 return rc;
126 }
127
128 rc = write_buf_to_fd(lh->fd, buf, len);
129 if (rc)
130 return rc;
131
132 lh->size += len;
133
134 return 0;
135}
136
137static void log_fini(struct handler *handler)
138{
139 struct log_handler *lh = to_log_handler(handler);
140 close(lh->fd);
141}
142
143static struct log_handler log_handler = {
144 .handler = {
145 .name = "log",
146 .init = log_init,
Jeremy Kerr3f54de42016-03-09 18:10:15 +0800147 .data_in = log_data,
148 .fini = log_fini,
149 },
150};
151
152console_register_handler(&log_handler.handler);
153