1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1997 Sandro Sigala, Brescia, Italy.
5 * Copyright (c) 1997 Chris Shenton
6 * Copyright (c) 1995 Søren Schmidt
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in this position and unchanged.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/jail.h>
38 #include <sys/kernel.h>
39 #include <sys/sysctl.h>
40 #include <sys/consio.h>
41 #include <sys/fbio.h>
42
43 #include <machine/pc/display.h>
44
45 #include <dev/fb/fbreg.h>
46 #include <dev/fb/splashreg.h>
47 #include <dev/syscons/syscons.h>
48
49 #define DAEMON_MAX_WIDTH 32
50 #define DAEMON_MAX_HEIGHT 19
51
52 static u_char *message;
53 static int messagelen;
54 static int blanked;
55 static int attr_mask;
56
57 #define ATTR(attr) (((attr) & attr_mask) << 8)
58
59 /* Who is the author of this ASCII pic? */
60
61 static u_char *daemon_pic[] = {
62 " , ,",
63 " /( )`",
64 " \\ \\___ / |",
65 " /- _ `-/ '",
66 " (/\\/ \\ \\ /\\",
67 " / / | ` \\",
68 " O O ) / |",
69 " `-^--'`< '",
70 " (_.) _ ) /",
71 " `.___/` /",
72 " `-----' /",
73 "<----. __ / __ \\",
74 "<----|====O)))==) \\) /====",
75 "<----' `--' `.__,' \\",
76 " | |",
77 " \\ / /\\",
78 " ______( (_ / \\______/",
79 " ,' ,-----' |",
80 " `--{__________)",
81 NULL
82 };
83
84 static u_char *daemon_attr[] = {
85 " R R",
86 " RR RR",
87 " R RRRR R R",
88 " RR W RRR R",
89 " RWWW W R RR",
90 " W W W R R",
91 " B B W R R",
92 " WWWWWWRR R",
93 " RRRR R R R",
94 " RRRRRRR R",
95 " RRRRRRR R",
96 "YYYYYY RR R RR R",
97 "YYYYYYYYYYRRRRYYR RR RYYYY",
98 "YYYYYY RRRR RRRRRR R",
99 " R R",
100 " R R RR",
101 " CCCCCCR RR R RRRRRRRR",
102 " CC CCCCCCC C",
103 " CCCCCCCCCCCCCCC",
104 NULL
105 };
106
107 /*
108 * Reverse a graphics character, or return unaltered if no mirror;
109 * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov>
110 */
111
112 static u_char
113 xflip_symbol(u_char symbol)
114 {
115 static const u_char lchars[] = "`'(){}[]\\/<>";
116 static const u_char rchars[] = "'`)(}{][/\\><";
117 int pos;
118
119 for (pos = 0; lchars[pos] != '\0'; pos++)
120 if (lchars[pos] == symbol)
121 return rchars[pos];
122
123 return symbol;
124 }
125
126 static void
127 clear_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
128 int xlen, int ylen)
129 {
130 int y;
131
132 if (xlen <= 0)
133 return;
134 for (y = yoff; y < ylen; y++) {
135 sc_vtb_erase(&sc->cur_scp->scr,
136 (ypos + y)*sc->cur_scp->xsize + xpos + xoff,
137 xlen - xoff,
138 sc->scr_map[0x20], ATTR(FG_LIGHTGREY | BG_BLACK));
139 }
140 }
141
142 static void
143 draw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
144 int xlen, int ylen)
145 {
146 int x, y;
147 int px;
148 int attr;
149
150 for (y = yoff; y < ylen; y++) {
151 if (dxdir < 0)
152 px = xoff;
153 else
154 px = DAEMON_MAX_WIDTH - xlen;
155 if (px >= strlen(daemon_pic[y]))
156 continue;
157 for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) {
158 switch (daemon_attr[y][px]) {
159 case 'R': attr = FG_LIGHTRED | BG_BLACK; break;
160 case 'Y': attr = FG_YELLOW | BG_BLACK; break;
161 case 'B': attr = FG_LIGHTBLUE | BG_BLACK; break;
162 case 'W': attr = FG_LIGHTGREY | BG_BLACK; break;
163 case 'C': attr = FG_CYAN | BG_BLACK; break;
164 default: attr = FG_WHITE | BG_BLACK; break;
165 }
166 if (dxdir < 0) { /* Moving left */
167 sc_vtb_putc(&sc->cur_scp->scr,
168 (ypos + y)*sc->cur_scp->xsize
169 + xpos + x,
170 sc->scr_map[daemon_pic[y][px]],
171 ATTR(attr));
172 } else { /* Moving right */
173 sc_vtb_putc(&sc->cur_scp->scr,
174 (ypos + y)*sc->cur_scp->xsize
175 + xpos + DAEMON_MAX_WIDTH
176 - px - 1,
177 sc->scr_map[xflip_symbol(daemon_pic[y][px])],
178 ATTR(attr));
179 }
180 }
181 }
182 }
183
184 static void
185 clear_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
186 {
187 if (len <= 0)
188 return;
189 sc_vtb_erase(&sc->cur_scp->scr,
190 ypos*sc->cur_scp->xsize + xpos + xoff, len - xoff,
191 sc->scr_map[0x20], ATTR(FG_LIGHTGREY | BG_BLACK));
192 }
193
194 static void
195 draw_string(sc_softc_t *sc, int xpos, int ypos, int xoff, u_char *s, int len)
196 {
197 int x;
198
199 for (x = xoff; x < len; x++)
200 sc_vtb_putc(&sc->cur_scp->scr,
201 ypos*sc->cur_scp->xsize + xpos + x,
202 sc->scr_map[s[x]], ATTR(FG_LIGHTGREEN | BG_BLACK));
203 }
204
205 static int
206 daemon_saver(video_adapter_t *adp, int blank)
207 {
208 static int txpos = 10, typos = 10;
209 static int txdir = -1, tydir = -1;
210 static int dxpos = 0, dypos = 0;
211 static int dxdir = 1, dydir = 1;
212 static int moved_daemon = 0;
213 static int xoff, yoff, toff;
214 static int xlen, ylen, tlen;
215 sc_softc_t *sc;
216 scr_stat *scp;
217 int min, max;
218
219 sc = sc_find_softc(adp, NULL);
220 if (sc == NULL)
221 return EAGAIN;
222 scp = sc->cur_scp;
223
224 if (blank) {
225 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
226 return EAGAIN;
227 if (blanked == 0) {
228 /* clear the screen and set the border color */
229 sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
230 ATTR(FG_LIGHTGREY | BG_BLACK));
231 vidd_set_hw_cursor(adp, -1, -1);
232 sc_set_border(scp, 0);
233 xlen = ylen = tlen = 0;
234 }
235 if (blanked++ < 2)
236 return 0;
237 blanked = 1;
238
239 clear_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
240 clear_string(sc, txpos, typos, toff, message, tlen);
241
242 if (++moved_daemon) {
243 /*
244 * The daemon picture may be off the screen, if
245 * screen size is chagened while the screen
246 * saver is inactive. Make sure the origin of
247 * the picture is between min and max.
248 */
249 if (scp->xsize <= DAEMON_MAX_WIDTH) {
250 /*
251 * If the screen width is too narrow, we
252 * allow part of the picture go off
253 * the screen so that the daemon won't
254 * flip too often.
255 */
256 min = scp->xsize - DAEMON_MAX_WIDTH - 10;
257 max = 10;
258 } else {
259 min = 0;
260 max = scp->xsize - DAEMON_MAX_WIDTH;
261 }
262 if (dxpos <= min) {
263 dxpos = min;
264 dxdir = 1;
265 } else if (dxpos >= max) {
266 dxpos = max;
267 dxdir = -1;
268 }
269
270 if (scp->ysize <= DAEMON_MAX_HEIGHT) {
271 min = scp->ysize - DAEMON_MAX_HEIGHT - 10;
272 max = 10;
273 } else {
274 min = 0;
275 max = scp->ysize - DAEMON_MAX_HEIGHT;
276 }
277 if (dypos <= min) {
278 dypos = min;
279 dydir = 1;
280 } else if (dypos >= max) {
281 dypos = max;
282 dydir = -1;
283 }
284
285 moved_daemon = -1;
286 dxpos += dxdir; dypos += dydir;
287
288 /* clip the picture */
289 xoff = 0;
290 xlen = DAEMON_MAX_WIDTH;
291 if (dxpos + xlen <= 0)
292 xlen = 0;
293 else if (dxpos < 0)
294 xoff = -dxpos;
295 if (dxpos >= scp->xsize)
296 xlen = 0;
297 else if (dxpos + xlen > scp->xsize)
298 xlen = scp->xsize - dxpos;
299 yoff = 0;
300 ylen = DAEMON_MAX_HEIGHT;
301 if (dypos + ylen <= 0)
302 ylen = 0;
303 else if (dypos < 0)
304 yoff = -dypos;
305 if (dypos >= scp->ysize)
306 ylen = 0;
307 else if (dypos + ylen > scp->ysize)
308 ylen = scp->ysize - dypos;
309 }
310
311 if (scp->xsize <= messagelen) {
312 min = scp->xsize - messagelen - 10;
313 max = 10;
314 } else {
315 min = 0;
316 max = scp->xsize - messagelen;
317 }
318 if (txpos <= min) {
319 txpos = min;
320 txdir = 1;
321 } else if (txpos >= max) {
322 txpos = max;
323 txdir = -1;
324 }
325 if (typos <= 0) {
326 typos = 0;
327 tydir = 1;
328 } else if (typos >= scp->ysize - 1) {
329 typos = scp->ysize - 1;
330 tydir = -1;
331 }
332 txpos += txdir; typos += tydir;
333
334 toff = 0;
335 tlen = messagelen;
336 if (txpos + tlen <= 0)
337 tlen = 0;
338 else if (txpos < 0)
339 toff = -txpos;
340 if (txpos >= scp->xsize)
341 tlen = 0;
342 else if (txpos + tlen > scp->xsize)
343 tlen = scp->xsize - txpos;
344
345 draw_daemon(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
346 draw_string(sc, txpos, typos, toff, message, tlen);
347 } else
348 blanked = 0;
349
350 return 0;
351 }
352
353 static int
354 daemon_init(video_adapter_t *adp)
355 {
356 size_t hostlen;
357
358 mtx_lock(&prison0.pr_mtx);
359 for (;;) {
360 hostlen = strlen(prison0.pr_hostname);
361 mtx_unlock(&prison0.pr_mtx);
362
363 messagelen = hostlen + 3 + strlen(ostype) + 1 +
364 strlen(osrelease);
365 message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK);
366 mtx_lock(&prison0.pr_mtx);
367 if (hostlen < strlen(prison0.pr_hostname)) {
368 free(message, M_DEVBUF);
369 continue;
370 }
371 break;
372 }
373 sprintf(message, "%s - %s %s", prison0.pr_hostname, ostype, osrelease);
374 mtx_unlock(&prison0.pr_mtx);
375 blanked = 0;
376 attr_mask = ~0;
377
378 return 0;
379 }
380
381 static int
382 daemon_term(video_adapter_t *adp)
383 {
384 free(message, M_DEVBUF);
385 return 0;
386 }
387
388 static scrn_saver_t daemon_module = {
389 "daemon_saver", daemon_init, daemon_term, daemon_saver, NULL,
390 };
391
392 SAVER_MODULE(daemon_saver, daemon_module);
Cache object: 97afadd929e029536e34e5e52de260de
|