]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/syscons/daemon/daemon_saver.c
MFV r350080:
[FreeBSD/FreeBSD.git] / sys / dev / syscons / daemon / daemon_saver.c
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);