xref: /linux/drivers/gpu/drm/drm_panic.c (revision f88cb2660bd09fd76b54e6bd2e62f3d7501147b6)
1 // SPDX-License-Identifier: GPL-2.0 or MIT
2 /*
3  * Copyright (c) 2023 Red Hat.
4  * Author: Jocelyn Falempe <jfalempe@redhat.com>
5  * inspired by the drm_log driver from David Herrmann <dh.herrmann@gmail.com>
6  * Tux Ascii art taken from cowsay written by Tony Monroe
7  */
8 
9 #include <linux/export.h>
10 #include <linux/font.h>
11 #include <linux/highmem.h>
12 #include <linux/init.h>
13 #include <linux/iosys-map.h>
14 #include <linux/kdebug.h>
15 #include <linux/kmsg_dump.h>
16 #include <linux/linux_logo.h>
17 #include <linux/list.h>
18 #include <linux/math.h>
19 #include <linux/module.h>
20 #include <linux/overflow.h>
21 #include <linux/printk.h>
22 #include <linux/types.h>
23 #include <linux/utsname.h>
24 #include <linux/zlib.h>
25 
26 #include <drm/drm_drv.h>
27 #include <drm/drm_fourcc.h>
28 #include <drm/drm_framebuffer.h>
29 #include <drm/drm_modeset_helper_vtables.h>
30 #include <drm/drm_panic.h>
31 #include <drm/drm_plane.h>
32 #include <drm/drm_print.h>
33 #include <drm/drm_rect.h>
34 
35 #include "drm_crtc_internal.h"
36 #include "drm_draw_internal.h"
37 
38 MODULE_AUTHOR("Jocelyn Falempe");
39 MODULE_DESCRIPTION("DRM panic handler");
40 MODULE_LICENSE("GPL");
41 
42 /**
43  * DOC: overview
44  *
45  * To enable DRM panic for a driver, the primary plane must implement a
46  * &drm_plane_helper_funcs.get_scanout_buffer helper function. It is then
47  * automatically registered to the drm panic handler.
48  * When a panic occurs, the &drm_plane_helper_funcs.get_scanout_buffer will be
49  * called, and the driver can provide a framebuffer so the panic handler can
50  * draw the panic screen on it. Currently only linear buffer and a few color
51  * formats are supported.
52  * Optionally the driver can also provide a &drm_plane_helper_funcs.panic_flush
53  * callback, that will be called after that, to send additional commands to the
54  * hardware to make the scanout buffer visible.
55  */
56 
57 /*
58  * This module displays a user friendly message on screen when a kernel panic
59  * occurs. This is conflicting with fbcon, so you can only enable it when fbcon
60  * is disabled.
61  * It's intended for end-user, so have minimal technical/debug information.
62  *
63  * Implementation details:
64  *
65  * It is a panic handler, so it can't take lock, allocate memory, run tasks/irq,
66  * or attempt to sleep. It's a best effort, and it may not be able to display
67  * the message in all situations (like if the panic occurs in the middle of a
68  * modesetting).
69  * It will display only one static frame, so performance optimizations are low
70  * priority as the machine is already in an unusable state.
71  */
72 
73 struct drm_panic_line {
74 	u32 len;
75 	const char *txt;
76 };
77 
78 #define PANIC_LINE(s) {.len = sizeof(s) - 1, .txt = s}
79 
80 static struct drm_panic_line panic_msg[] = {
81 	PANIC_LINE("KERNEL PANIC!"),
82 	PANIC_LINE(""),
83 	PANIC_LINE("Please reboot your computer."),
84 	PANIC_LINE(""),
85 	PANIC_LINE(""), /* will be replaced by the panic description */
86 };
87 
88 static const size_t panic_msg_lines = ARRAY_SIZE(panic_msg);
89 
90 static const struct drm_panic_line logo_ascii[] = {
91 	PANIC_LINE("     .--.        _"),
92 	PANIC_LINE("    |o_o |      | |"),
93 	PANIC_LINE("    |:_/ |      | |"),
94 	PANIC_LINE("   //   \\ \\     |_|"),
95 	PANIC_LINE("  (|     | )     _"),
96 	PANIC_LINE(" /'\\_   _/`\\    (_)"),
97 	PANIC_LINE(" \\___)=(___/"),
98 };
99 
100 static const size_t logo_ascii_lines = ARRAY_SIZE(logo_ascii);
101 
102 #if defined(CONFIG_LOGO) && !defined(MODULE)
103 static const struct linux_logo *logo_mono;
104 
105 static int drm_panic_setup_logo(void)
106 {
107 	const struct linux_logo *logo = fb_find_logo(1);
108 	const unsigned char *logo_data;
109 	struct linux_logo *logo_dup;
110 
111 	if (!logo || logo->type != LINUX_LOGO_MONO)
112 		return 0;
113 
114 	/* The logo is __init, so we must make a copy for later use */
115 	logo_data = kmemdup(logo->data,
116 			    size_mul(DIV_ROUND_UP(logo->width, BITS_PER_BYTE), logo->height),
117 			    GFP_KERNEL);
118 	if (!logo_data)
119 		return -ENOMEM;
120 
121 	logo_dup = kmemdup(logo, sizeof(*logo), GFP_KERNEL);
122 	if (!logo_dup) {
123 		kfree(logo_data);
124 		return -ENOMEM;
125 	}
126 
127 	logo_dup->data = logo_data;
128 	logo_mono = logo_dup;
129 
130 	return 0;
131 }
132 
133 device_initcall(drm_panic_setup_logo);
134 #else
135 #define logo_mono	((const struct linux_logo *)NULL)
136 #endif
137 
138 /*
139  *  Blit & Fill functions
140  */
141 static void drm_panic_blit_pixel(struct drm_scanout_buffer *sb, struct drm_rect *clip,
142 				 const u8 *sbuf8, unsigned int spitch, unsigned int scale,
143 				 u32 fg_color)
144 {
145 	unsigned int y, x;
146 
147 	for (y = 0; y < drm_rect_height(clip); y++)
148 		for (x = 0; x < drm_rect_width(clip); x++)
149 			if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale))
150 				sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, fg_color);
151 }
152 
153 static void drm_panic_write_pixel16(void *vaddr, unsigned int offset, u16 color)
154 {
155 	u16 *p = vaddr + offset;
156 
157 	*p = color;
158 }
159 
160 static void drm_panic_write_pixel24(void *vaddr, unsigned int offset, u32 color)
161 {
162 	u8 *p = vaddr + offset;
163 
164 	*p++ = color & 0xff;
165 	color >>= 8;
166 	*p++ = color & 0xff;
167 	color >>= 8;
168 	*p = color & 0xff;
169 }
170 
171 static void drm_panic_write_pixel32(void *vaddr, unsigned int offset, u32 color)
172 {
173 	u32 *p = vaddr + offset;
174 
175 	*p = color;
176 }
177 
178 static void drm_panic_write_pixel(void *vaddr, unsigned int offset, u32 color, unsigned int cpp)
179 {
180 	switch (cpp) {
181 	case 2:
182 		drm_panic_write_pixel16(vaddr, offset, color);
183 		break;
184 	case 3:
185 		drm_panic_write_pixel24(vaddr, offset, color);
186 		break;
187 	case 4:
188 		drm_panic_write_pixel32(vaddr, offset, color);
189 		break;
190 	default:
191 		pr_debug_once("Can't blit with pixel width %d\n", cpp);
192 	}
193 }
194 
195 /*
196  * The scanout buffer pages are not mapped, so for each pixel,
197  * use kmap_local_page_try_from_panic() to map the page, and write the pixel.
198  * Try to keep the map from the previous pixel, to avoid too much map/unmap.
199  */
200 static void drm_panic_blit_page(struct page **pages, unsigned int dpitch,
201 				unsigned int cpp, const u8 *sbuf8,
202 				unsigned int spitch, struct drm_rect *clip,
203 				unsigned int scale, u32 fg32)
204 {
205 	unsigned int y, x;
206 	unsigned int page = ~0;
207 	unsigned int height = drm_rect_height(clip);
208 	unsigned int width = drm_rect_width(clip);
209 	void *vaddr = NULL;
210 
211 	for (y = 0; y < height; y++) {
212 		for (x = 0; x < width; x++) {
213 			if (drm_draw_is_pixel_fg(sbuf8, spitch, x / scale, y / scale)) {
214 				unsigned int new_page;
215 				unsigned int offset;
216 
217 				offset = (y + clip->y1) * dpitch + (x + clip->x1) * cpp;
218 				new_page = offset >> PAGE_SHIFT;
219 				offset = offset % PAGE_SIZE;
220 				if (new_page != page) {
221 					if (!pages[new_page])
222 						continue;
223 					if (vaddr)
224 						kunmap_local(vaddr);
225 					page = new_page;
226 					vaddr = kmap_local_page_try_from_panic(pages[page]);
227 				}
228 				if (vaddr)
229 					drm_panic_write_pixel(vaddr, offset, fg32, cpp);
230 			}
231 		}
232 	}
233 	if (vaddr)
234 		kunmap_local(vaddr);
235 }
236 
237 /*
238  * drm_panic_blit - convert a monochrome image to a linear framebuffer
239  * @sb: destination scanout buffer
240  * @clip: destination rectangle
241  * @sbuf8: source buffer, in monochrome format, 8 pixels per byte.
242  * @spitch: source pitch in bytes
243  * @scale: integer scale, source buffer is scale time smaller than destination
244  *         rectangle
245  * @fg_color: foreground color, in destination format
246  *
247  * This can be used to draw a font character, which is a monochrome image, to a
248  * framebuffer in other supported format.
249  */
250 static void drm_panic_blit(struct drm_scanout_buffer *sb, struct drm_rect *clip,
251 			   const u8 *sbuf8, unsigned int spitch,
252 			   unsigned int scale, u32 fg_color)
253 
254 {
255 	struct iosys_map map;
256 
257 	if (sb->set_pixel)
258 		return drm_panic_blit_pixel(sb, clip, sbuf8, spitch, scale, fg_color);
259 
260 	if (sb->pages)
261 		return drm_panic_blit_page(sb->pages, sb->pitch[0], sb->format->cpp[0],
262 					   sbuf8, spitch, clip, scale, fg_color);
263 
264 	map = sb->map[0];
265 	iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]);
266 
267 	switch (sb->format->cpp[0]) {
268 	case 2:
269 		drm_draw_blit16(&map, sb->pitch[0], sbuf8, spitch,
270 				drm_rect_height(clip), drm_rect_width(clip), scale, fg_color);
271 	break;
272 	case 3:
273 		drm_draw_blit24(&map, sb->pitch[0], sbuf8, spitch,
274 				drm_rect_height(clip), drm_rect_width(clip), scale, fg_color);
275 	break;
276 	case 4:
277 		drm_draw_blit32(&map, sb->pitch[0], sbuf8, spitch,
278 				drm_rect_height(clip), drm_rect_width(clip), scale, fg_color);
279 	break;
280 	default:
281 		WARN_ONCE(1, "Can't blit with pixel width %d\n", sb->format->cpp[0]);
282 	}
283 }
284 
285 static void drm_panic_fill_pixel(struct drm_scanout_buffer *sb,
286 				 struct drm_rect *clip,
287 				 u32 color)
288 {
289 	unsigned int y, x;
290 
291 	for (y = 0; y < drm_rect_height(clip); y++)
292 		for (x = 0; x < drm_rect_width(clip); x++)
293 			sb->set_pixel(sb, clip->x1 + x, clip->y1 + y, color);
294 }
295 
296 static void drm_panic_fill_page(struct page **pages, unsigned int dpitch,
297 				unsigned int cpp, struct drm_rect *clip,
298 				u32 color)
299 {
300 	unsigned int y, x;
301 	unsigned int page = ~0;
302 	void *vaddr = NULL;
303 
304 	for (y = clip->y1; y < clip->y2; y++) {
305 		for (x = clip->x1; x < clip->x2; x++) {
306 			unsigned int new_page;
307 			unsigned int offset;
308 
309 			offset = y * dpitch + x * cpp;
310 			new_page = offset >> PAGE_SHIFT;
311 			offset = offset % PAGE_SIZE;
312 			if (new_page != page) {
313 				if (vaddr)
314 					kunmap_local(vaddr);
315 				page = new_page;
316 				vaddr = kmap_local_page_try_from_panic(pages[page]);
317 			}
318 			drm_panic_write_pixel(vaddr, offset, color, cpp);
319 		}
320 	}
321 	if (vaddr)
322 		kunmap_local(vaddr);
323 }
324 
325 /*
326  * drm_panic_fill - Fill a rectangle with a color
327  * @sb: destination scanout buffer
328  * @clip: destination rectangle
329  * @color: foreground color, in destination format
330  *
331  * Fill a rectangle with a color, in a linear framebuffer.
332  */
333 static void drm_panic_fill(struct drm_scanout_buffer *sb, struct drm_rect *clip,
334 			   u32 color)
335 {
336 	struct iosys_map map;
337 
338 	if (sb->set_pixel)
339 		return drm_panic_fill_pixel(sb, clip, color);
340 
341 	if (sb->pages)
342 		return drm_panic_fill_page(sb->pages, sb->pitch[0], sb->format->cpp[0],
343 					   clip, color);
344 
345 	map = sb->map[0];
346 	iosys_map_incr(&map, clip->y1 * sb->pitch[0] + clip->x1 * sb->format->cpp[0]);
347 
348 	switch (sb->format->cpp[0]) {
349 	case 2:
350 		drm_draw_fill16(&map, sb->pitch[0], drm_rect_height(clip),
351 				drm_rect_width(clip), color);
352 	break;
353 	case 3:
354 		drm_draw_fill24(&map, sb->pitch[0], drm_rect_height(clip),
355 				drm_rect_width(clip), color);
356 	break;
357 	case 4:
358 		drm_draw_fill32(&map, sb->pitch[0], drm_rect_height(clip),
359 				drm_rect_width(clip), color);
360 	break;
361 	default:
362 		WARN_ONCE(1, "Can't fill with pixel width %d\n", sb->format->cpp[0]);
363 	}
364 }
365 
366 static unsigned int get_max_line_len(const struct drm_panic_line *lines, int len)
367 {
368 	int i;
369 	unsigned int max = 0;
370 
371 	for (i = 0; i < len; i++)
372 		max = max(lines[i].len, max);
373 	return max;
374 }
375 
376 /*
377  * Draw a text in a rectangle on a framebuffer. The text is truncated if it overflows the rectangle
378  */
379 static void draw_txt_rectangle(struct drm_scanout_buffer *sb,
380 			       const struct font_desc *font,
381 			       const struct drm_panic_line *msg,
382 			       unsigned int msg_lines,
383 			       bool centered,
384 			       struct drm_rect *clip,
385 			       u32 color)
386 {
387 	int i, j;
388 	const u8 *src;
389 	size_t font_pitch = DIV_ROUND_UP(font->width, 8);
390 	struct drm_rect rec;
391 
392 	msg_lines = min(msg_lines,  drm_rect_height(clip) / font->height);
393 	for (i = 0; i < msg_lines; i++) {
394 		size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width);
395 
396 		rec.y1 = clip->y1 +  i * font->height;
397 		rec.y2 = rec.y1 + font->height;
398 		rec.x1 = clip->x1;
399 
400 		if (centered)
401 			rec.x1 += (drm_rect_width(clip) - (line_len * font->width)) / 2;
402 
403 		for (j = 0; j < line_len; j++) {
404 			src = drm_draw_get_char_bitmap(font, msg[i].txt[j], font_pitch);
405 			rec.x2 = rec.x1 + font->width;
406 			drm_panic_blit(sb, &rec, src, font_pitch, 1, color);
407 			rec.x1 += font->width;
408 		}
409 	}
410 }
411 
412 static void drm_panic_logo_rect(struct drm_rect *rect, const struct font_desc *font)
413 {
414 	if (logo_mono) {
415 		drm_rect_init(rect, 0, 0, logo_mono->width, logo_mono->height);
416 	} else {
417 		int logo_width = get_max_line_len(logo_ascii, logo_ascii_lines) * font->width;
418 
419 		drm_rect_init(rect, 0, 0, logo_width, logo_ascii_lines * font->height);
420 	}
421 }
422 
423 static void drm_panic_logo_draw(struct drm_scanout_buffer *sb, struct drm_rect *rect,
424 				const struct font_desc *font, u32 fg_color)
425 {
426 	if (logo_mono)
427 		drm_panic_blit(sb, rect, logo_mono->data,
428 			       DIV_ROUND_UP(drm_rect_width(rect), 8), 1, fg_color);
429 	else
430 		draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, rect,
431 				   fg_color);
432 }
433 
434 static void draw_panic_static_user(struct drm_scanout_buffer *sb)
435 {
436 	u32 fg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR,
437 						    sb->format->format);
438 	u32 bg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR,
439 						    sb->format->format);
440 	const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
441 	struct drm_rect r_screen, r_logo, r_msg;
442 	unsigned int msg_width, msg_height;
443 
444 	if (!font)
445 		return;
446 
447 	r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
448 	drm_panic_logo_rect(&r_logo, font);
449 
450 	msg_width = min(get_max_line_len(panic_msg, panic_msg_lines) * font->width, sb->width);
451 	msg_height = min(panic_msg_lines * font->height, sb->height);
452 	r_msg = DRM_RECT_INIT(0, 0, msg_width, msg_height);
453 
454 	/* Center the panic message */
455 	drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2);
456 
457 	/* Fill with the background color, and draw text on top */
458 	drm_panic_fill(sb, &r_screen, bg_color);
459 
460 	if (!drm_rect_overlap(&r_logo, &r_msg))
461 		drm_panic_logo_draw(sb, &r_logo, font, fg_color);
462 
463 	draw_txt_rectangle(sb, font, panic_msg, panic_msg_lines, true, &r_msg, fg_color);
464 }
465 
466 /*
467  * Draw one line of kmsg, and handle wrapping if it won't fit in the screen width.
468  * Return the y-offset of the next line.
469  */
470 static int draw_line_with_wrap(struct drm_scanout_buffer *sb, const struct font_desc *font,
471 			       struct drm_panic_line *line, int yoffset, u32 fg_color)
472 {
473 	int chars_per_row = sb->width / font->width;
474 	struct drm_rect r_txt = DRM_RECT_INIT(0, yoffset, sb->width, sb->height);
475 	struct drm_panic_line line_wrap;
476 
477 	if (line->len > chars_per_row) {
478 		line_wrap.len = line->len % chars_per_row;
479 		line_wrap.txt = line->txt + line->len - line_wrap.len;
480 		draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color);
481 		r_txt.y1 -= font->height;
482 		if (r_txt.y1 < 0)
483 			return r_txt.y1;
484 		while (line_wrap.txt > line->txt) {
485 			line_wrap.txt -= chars_per_row;
486 			line_wrap.len = chars_per_row;
487 			draw_txt_rectangle(sb, font, &line_wrap, 1, false, &r_txt, fg_color);
488 			r_txt.y1 -= font->height;
489 			if (r_txt.y1 < 0)
490 				return r_txt.y1;
491 		}
492 	} else {
493 		draw_txt_rectangle(sb, font, line, 1, false, &r_txt, fg_color);
494 		r_txt.y1 -= font->height;
495 	}
496 	return r_txt.y1;
497 }
498 
499 /*
500  * Draw the kmsg buffer to the screen, starting from the youngest message at the bottom,
501  * and going up until reaching the top of the screen.
502  */
503 static void draw_panic_static_kmsg(struct drm_scanout_buffer *sb)
504 {
505 	u32 fg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR,
506 						    sb->format->format);
507 	u32 bg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR,
508 						    sb->format->format);
509 	const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
510 	struct drm_rect r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
511 	struct kmsg_dump_iter iter;
512 	char kmsg_buf[512];
513 	size_t kmsg_len;
514 	struct drm_panic_line line;
515 	int yoffset;
516 
517 	if (!font)
518 		return;
519 
520 	yoffset = sb->height - font->height - (sb->height % font->height) / 2;
521 
522 	/* Fill with the background color, and draw text on top */
523 	drm_panic_fill(sb, &r_screen, bg_color);
524 
525 	kmsg_dump_rewind(&iter);
526 	while (kmsg_dump_get_buffer(&iter, false, kmsg_buf, sizeof(kmsg_buf), &kmsg_len)) {
527 		char *start;
528 		char *end;
529 
530 		/* ignore terminating NUL and newline */
531 		start = kmsg_buf + kmsg_len - 2;
532 		end = kmsg_buf + kmsg_len - 1;
533 		while (start > kmsg_buf && yoffset >= 0) {
534 			while (start > kmsg_buf && *start != '\n')
535 				start--;
536 			/* don't count the newline character */
537 			line.txt = start + (start == kmsg_buf ? 0 : 1);
538 			line.len = end - line.txt;
539 
540 			yoffset = draw_line_with_wrap(sb, font, &line, yoffset, fg_color);
541 			end = start;
542 			start--;
543 		}
544 	}
545 }
546 
547 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
548 /*
549  * It is unwise to allocate memory in the panic callback, so the buffers are
550  * pre-allocated. Only 2 buffers and the zlib workspace are needed.
551  * Two buffers are enough, using the following buffer usage:
552  * 1) kmsg messages are dumped in buffer1
553  * 2) kmsg is zlib-compressed into buffer2
554  * 3) compressed kmsg is encoded as QR-code Numeric stream in buffer1
555  * 4) QR-code image is generated in buffer2
556  * The Max QR code size is V40, 177x177, 4071 bytes for image, 2956 bytes for
557  * data segments.
558  *
559  * Typically, ~7500 bytes of kmsg, are compressed into 2800 bytes, which fits in
560  * a V40 QR-code (177x177).
561  *
562  * If CONFIG_DRM_PANIC_SCREEN_QR_CODE_URL is not set, the kmsg data will be put
563  * directly in the QR code.
564  * 1) kmsg messages are dumped in buffer1
565  * 2) kmsg message is encoded as byte stream in buffer2
566  * 3) QR-code image is generated in buffer1
567  */
568 
569 static uint panic_qr_version = CONFIG_DRM_PANIC_SCREEN_QR_VERSION;
570 module_param(panic_qr_version, uint, 0644);
571 MODULE_PARM_DESC(panic_qr_version, "maximum version (size) of the QR code");
572 
573 #define MAX_QR_DATA 2956
574 #define MAX_ZLIB_RATIO 3
575 #define QR_BUFFER1_SIZE (MAX_ZLIB_RATIO * MAX_QR_DATA) /* Must also be > 4071  */
576 #define QR_BUFFER2_SIZE 4096
577 #define QR_MARGIN	4	/* 4 modules of foreground color around the qr code */
578 
579 /* Compression parameters */
580 #define COMPR_LEVEL 6
581 #define WINDOW_BITS 12
582 #define MEM_LEVEL 4
583 
584 static char *qrbuf1;
585 static char *qrbuf2;
586 static struct z_stream_s stream;
587 
588 static void __init drm_panic_qr_init(void)
589 {
590 	qrbuf1 = kmalloc(QR_BUFFER1_SIZE, GFP_KERNEL);
591 	qrbuf2 = kmalloc(QR_BUFFER2_SIZE, GFP_KERNEL);
592 	stream.workspace = kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
593 				   GFP_KERNEL);
594 }
595 
596 static void drm_panic_qr_exit(void)
597 {
598 	kfree(qrbuf1);
599 	qrbuf1 = NULL;
600 	kfree(qrbuf2);
601 	qrbuf2 = NULL;
602 	kfree(stream.workspace);
603 	stream.workspace = NULL;
604 }
605 
606 static int drm_panic_get_qr_code_url(u8 **qr_image)
607 {
608 	struct kmsg_dump_iter iter;
609 	char url[256];
610 	size_t kmsg_len, max_kmsg_size;
611 	char *kmsg;
612 	int max_qr_data_size, url_len;
613 
614 	url_len = snprintf(url, sizeof(url), CONFIG_DRM_PANIC_SCREEN_QR_CODE_URL "?a=%s&v=%s&z=",
615 			   utsname()->machine, utsname()->release);
616 
617 	max_qr_data_size = drm_panic_qr_max_data_size(panic_qr_version, url_len);
618 	max_kmsg_size = min(MAX_ZLIB_RATIO * max_qr_data_size, QR_BUFFER1_SIZE);
619 
620 	/* get kmsg to buffer 1 */
621 	kmsg_dump_rewind(&iter);
622 	kmsg_dump_get_buffer(&iter, false, qrbuf1, max_kmsg_size, &kmsg_len);
623 
624 	if (!kmsg_len)
625 		return -ENODATA;
626 	kmsg = qrbuf1;
627 
628 try_again:
629 	if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
630 			      MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
631 		return -EINVAL;
632 
633 	stream.next_in = kmsg;
634 	stream.avail_in = kmsg_len;
635 	stream.total_in = 0;
636 	stream.next_out = qrbuf2;
637 	stream.avail_out = QR_BUFFER2_SIZE;
638 	stream.total_out = 0;
639 
640 	if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END)
641 		return -EINVAL;
642 
643 	if (zlib_deflateEnd(&stream) != Z_OK)
644 		return -EINVAL;
645 
646 	if (stream.total_out > max_qr_data_size) {
647 		/* too much data for the QR code, so skip the first line and try again */
648 		kmsg = strchr(kmsg, '\n');
649 		if (!kmsg)
650 			return -EINVAL;
651 		/* skip the first \n */
652 		kmsg += 1;
653 		kmsg_len = strlen(kmsg);
654 		goto try_again;
655 	}
656 	*qr_image = qrbuf2;
657 
658 	/* generate qr code image in buffer2 */
659 	return drm_panic_qr_generate(url, qrbuf2, stream.total_out, QR_BUFFER2_SIZE,
660 				     qrbuf1, QR_BUFFER1_SIZE);
661 }
662 
663 static int drm_panic_get_qr_code_raw(u8 **qr_image)
664 {
665 	struct kmsg_dump_iter iter;
666 	size_t kmsg_len;
667 	size_t max_kmsg_size = min(drm_panic_qr_max_data_size(panic_qr_version, 0),
668 				   QR_BUFFER1_SIZE);
669 
670 	kmsg_dump_rewind(&iter);
671 	kmsg_dump_get_buffer(&iter, false, qrbuf1, max_kmsg_size, &kmsg_len);
672 	if (!kmsg_len)
673 		return -ENODATA;
674 
675 	*qr_image = qrbuf1;
676 	return drm_panic_qr_generate(NULL, qrbuf1, kmsg_len, QR_BUFFER1_SIZE,
677 				     qrbuf2, QR_BUFFER2_SIZE);
678 }
679 
680 static int drm_panic_get_qr_code(u8 **qr_image)
681 {
682 	if (strlen(CONFIG_DRM_PANIC_SCREEN_QR_CODE_URL) > 0)
683 		return drm_panic_get_qr_code_url(qr_image);
684 	else
685 		return drm_panic_get_qr_code_raw(qr_image);
686 }
687 
688 /*
689  * Draw the panic message at the center of the screen, with a QR Code
690  */
691 static int _draw_panic_static_qr_code(struct drm_scanout_buffer *sb)
692 {
693 	u32 fg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR,
694 						    sb->format->format);
695 	u32 bg_color = drm_draw_color_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR,
696 						    sb->format->format);
697 	const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
698 	struct drm_rect r_screen, r_logo, r_msg, r_qr, r_qr_canvas;
699 	unsigned int max_qr_size, scale;
700 	unsigned int msg_width, msg_height;
701 	int qr_width, qr_canvas_width, qr_pitch, v_margin;
702 	u8 *qr_image;
703 
704 	if (!font || !qrbuf1 || !qrbuf2 || !stream.workspace)
705 		return -ENOMEM;
706 
707 	r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
708 
709 	drm_panic_logo_rect(&r_logo, font);
710 
711 	msg_width = min(get_max_line_len(panic_msg, panic_msg_lines) * font->width, sb->width);
712 	msg_height = min(panic_msg_lines * font->height, sb->height);
713 	r_msg = DRM_RECT_INIT(0, 0, msg_width, msg_height);
714 
715 	max_qr_size = min(3 * sb->width / 4, 3 * sb->height / 4);
716 
717 	qr_width = drm_panic_get_qr_code(&qr_image);
718 	if (qr_width <= 0)
719 		return -ENOSPC;
720 
721 	qr_canvas_width = qr_width + QR_MARGIN * 2;
722 	scale = max_qr_size / qr_canvas_width;
723 	/* QR code is not readable if not scaled at least by 2 */
724 	if (scale < 2)
725 		return -ENOSPC;
726 
727 	pr_debug("QR width %d and scale %d\n", qr_width, scale);
728 	r_qr_canvas = DRM_RECT_INIT(0, 0, qr_canvas_width * scale, qr_canvas_width * scale);
729 
730 	v_margin = (sb->height - drm_rect_height(&r_qr_canvas) - drm_rect_height(&r_msg)) / 5;
731 
732 	drm_rect_translate(&r_qr_canvas, (sb->width - r_qr_canvas.x2) / 2, 2 * v_margin);
733 	r_qr = DRM_RECT_INIT(r_qr_canvas.x1 + QR_MARGIN * scale, r_qr_canvas.y1 + QR_MARGIN * scale,
734 			     qr_width * scale, qr_width * scale);
735 
736 	/* Center the panic message */
737 	drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2,
738 			   3 * v_margin + drm_rect_height(&r_qr_canvas));
739 
740 	/* Fill with the background color, and draw text on top */
741 	drm_panic_fill(sb, &r_screen, bg_color);
742 
743 	if (!drm_rect_overlap(&r_logo, &r_msg) && !drm_rect_overlap(&r_logo, &r_qr))
744 		drm_panic_logo_draw(sb, &r_logo, font, fg_color);
745 
746 	draw_txt_rectangle(sb, font, panic_msg, panic_msg_lines, true, &r_msg, fg_color);
747 
748 	/* Draw the qr code */
749 	qr_pitch = DIV_ROUND_UP(qr_width, 8);
750 	drm_panic_fill(sb, &r_qr_canvas, fg_color);
751 	drm_panic_fill(sb, &r_qr, bg_color);
752 	drm_panic_blit(sb, &r_qr, qr_image, qr_pitch, scale, fg_color);
753 	return 0;
754 }
755 
756 static void draw_panic_static_qr_code(struct drm_scanout_buffer *sb)
757 {
758 	if (_draw_panic_static_qr_code(sb))
759 		draw_panic_static_user(sb);
760 }
761 #else
762 static void drm_panic_qr_init(void) {};
763 static void drm_panic_qr_exit(void) {};
764 #endif
765 
766 enum drm_panic_type {
767 	DRM_PANIC_TYPE_KMSG,
768 	DRM_PANIC_TYPE_USER,
769 	DRM_PANIC_TYPE_QR,
770 };
771 
772 static enum drm_panic_type drm_panic_type = -1;
773 
774 static const char *drm_panic_type_map[] = {
775 	[DRM_PANIC_TYPE_KMSG] = "kmsg",
776 	[DRM_PANIC_TYPE_USER] = "user",
777 #if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
778 	[DRM_PANIC_TYPE_QR] = "qr",
779 #endif
780 };
781 
782 static int drm_panic_type_set(const char *val, const struct kernel_param *kp)
783 {
784 	unsigned int i;
785 
786 	for (i = 0; i < ARRAY_SIZE(drm_panic_type_map); i++) {
787 		if (!strcmp(val, drm_panic_type_map[i])) {
788 			drm_panic_type = i;
789 			return 0;
790 		}
791 	}
792 
793 	return -EINVAL;
794 }
795 
796 static int drm_panic_type_get(char *buffer, const struct kernel_param *kp)
797 {
798 	return scnprintf(buffer, PAGE_SIZE, "%s\n",
799 			 drm_panic_type_map[drm_panic_type]);
800 }
801 
802 static const struct kernel_param_ops drm_panic_ops = {
803 	.set = drm_panic_type_set,
804 	.get = drm_panic_type_get,
805 };
806 
807 module_param_cb(panic_screen, &drm_panic_ops, NULL, 0644);
808 MODULE_PARM_DESC(panic_screen,
809 #if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
810 		 "Choose what will be displayed by drm_panic, 'user', 'kmsg' or 'qr' [default="
811 #else
812 		 "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default="
813 #endif
814 		 CONFIG_DRM_PANIC_SCREEN "]");
815 
816 /*
817  * drm_panic_is_format_supported()
818  * @format: a fourcc color code
819  * Returns: true if supported, false otherwise.
820  *
821  * Check if drm_panic will be able to use this color format.
822  */
823 static bool drm_panic_is_format_supported(const struct drm_format_info *format)
824 {
825 	if (format->num_planes != 1)
826 		return false;
827 	return drm_draw_color_from_xrgb8888(0xffffff, format->format) != 0;
828 }
829 
830 static void draw_panic_dispatch(struct drm_scanout_buffer *sb)
831 {
832 	switch (drm_panic_type) {
833 	case DRM_PANIC_TYPE_KMSG:
834 		draw_panic_static_kmsg(sb);
835 		break;
836 
837 #if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
838 	case DRM_PANIC_TYPE_QR:
839 		draw_panic_static_qr_code(sb);
840 		break;
841 #endif
842 
843 	case DRM_PANIC_TYPE_USER:
844 	default:
845 		draw_panic_static_user(sb);
846 	}
847 }
848 
849 static void drm_panic_set_description(const char *description)
850 {
851 	u32 len;
852 
853 	if (description) {
854 		struct drm_panic_line *desc_line = &panic_msg[panic_msg_lines - 1];
855 
856 		desc_line->txt = description;
857 		len = strlen(description);
858 		/* ignore the last newline character */
859 		if (len && description[len - 1] == '\n')
860 			len -= 1;
861 		desc_line->len = len;
862 	}
863 }
864 
865 static void drm_panic_clear_description(void)
866 {
867 	struct drm_panic_line *desc_line = &panic_msg[panic_msg_lines - 1];
868 
869 	desc_line->len = 0;
870 	desc_line->txt = NULL;
871 }
872 
873 static void draw_panic_plane(struct drm_plane *plane, const char *description)
874 {
875 	struct drm_scanout_buffer sb = { };
876 	int ret;
877 	unsigned long flags;
878 
879 	if (!drm_panic_trylock(plane->dev, flags))
880 		return;
881 
882 	ret = plane->helper_private->get_scanout_buffer(plane, &sb);
883 
884 	if (ret || !drm_panic_is_format_supported(sb.format))
885 		goto unlock;
886 
887 	/* One of these should be set, or it can't draw pixels */
888 	if (!sb.set_pixel && !sb.pages && iosys_map_is_null(&sb.map[0]))
889 		goto unlock;
890 
891 	drm_panic_set_description(description);
892 
893 	draw_panic_dispatch(&sb);
894 	if (plane->helper_private->panic_flush)
895 		plane->helper_private->panic_flush(plane);
896 
897 	drm_panic_clear_description();
898 
899 unlock:
900 	drm_panic_unlock(plane->dev, flags);
901 }
902 
903 static struct drm_plane *to_drm_plane(struct kmsg_dumper *kd)
904 {
905 	return container_of(kd, struct drm_plane, kmsg_panic);
906 }
907 
908 static void drm_panic(struct kmsg_dumper *dumper, struct kmsg_dump_detail *detail)
909 {
910 	struct drm_plane *plane = to_drm_plane(dumper);
911 
912 	if (detail->reason == KMSG_DUMP_PANIC)
913 		draw_panic_plane(plane, detail->description);
914 }
915 
916 
917 /*
918  * DEBUG FS, This is currently unsafe.
919  * Create one file per plane, so it's possible to debug one plane at a time.
920  * TODO: It would be better to emulate an NMI context.
921  */
922 #ifdef CONFIG_DRM_PANIC_DEBUG
923 #include <linux/debugfs.h>
924 
925 static ssize_t debugfs_trigger_write(struct file *file, const char __user *user_buf,
926 				     size_t count, loff_t *ppos)
927 {
928 	bool run;
929 
930 	if (kstrtobool_from_user(user_buf, count, &run) == 0 && run) {
931 		struct drm_plane *plane = file->private_data;
932 
933 		draw_panic_plane(plane, "Test from debugfs");
934 	}
935 	return count;
936 }
937 
938 static const struct file_operations dbg_drm_panic_ops = {
939 	.owner = THIS_MODULE,
940 	.write = debugfs_trigger_write,
941 	.open = simple_open,
942 };
943 
944 static void debugfs_register_plane(struct drm_plane *plane, int index)
945 {
946 	char fname[32];
947 
948 	snprintf(fname, 32, "drm_panic_plane_%d", index);
949 	debugfs_create_file(fname, 0200, plane->dev->debugfs_root,
950 			    plane, &dbg_drm_panic_ops);
951 }
952 #else
953 static void debugfs_register_plane(struct drm_plane *plane, int index) {}
954 #endif /* CONFIG_DRM_PANIC_DEBUG */
955 
956 /**
957  * drm_panic_is_enabled
958  * @dev: the drm device that may supports drm_panic
959  *
960  * returns true if the drm device supports drm_panic
961  */
962 bool drm_panic_is_enabled(struct drm_device *dev)
963 {
964 	struct drm_plane *plane;
965 
966 	if (!dev->mode_config.num_total_plane)
967 		return false;
968 
969 	drm_for_each_plane(plane, dev)
970 		if (plane->helper_private && plane->helper_private->get_scanout_buffer)
971 			return true;
972 	return false;
973 }
974 EXPORT_SYMBOL(drm_panic_is_enabled);
975 
976 /**
977  * drm_panic_register() - Initialize DRM panic for a device
978  * @dev: the drm device on which the panic screen will be displayed.
979  */
980 void drm_panic_register(struct drm_device *dev)
981 {
982 	struct drm_plane *plane;
983 	int registered_plane = 0;
984 
985 	if (!dev->mode_config.num_total_plane)
986 		return;
987 
988 	drm_for_each_plane(plane, dev) {
989 		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer)
990 			continue;
991 		plane->kmsg_panic.dump = drm_panic;
992 		plane->kmsg_panic.max_reason = KMSG_DUMP_PANIC;
993 		if (kmsg_dump_register(&plane->kmsg_panic))
994 			drm_warn(dev, "Failed to register panic handler\n");
995 		else {
996 			debugfs_register_plane(plane, registered_plane);
997 			registered_plane++;
998 		}
999 	}
1000 	if (registered_plane)
1001 		drm_info(dev, "Registered %d planes with drm panic\n", registered_plane);
1002 }
1003 
1004 /**
1005  * drm_panic_unregister()
1006  * @dev: the drm device previously registered.
1007  */
1008 void drm_panic_unregister(struct drm_device *dev)
1009 {
1010 	struct drm_plane *plane;
1011 
1012 	if (!dev->mode_config.num_total_plane)
1013 		return;
1014 
1015 	drm_for_each_plane(plane, dev) {
1016 		if (!plane->helper_private || !plane->helper_private->get_scanout_buffer)
1017 			continue;
1018 		kmsg_dump_unregister(&plane->kmsg_panic);
1019 	}
1020 }
1021 
1022 /**
1023  * drm_panic_init() - initialize DRM panic.
1024  */
1025 void __init drm_panic_init(void)
1026 {
1027 	if (drm_panic_type == -1)
1028 		drm_panic_type_set(CONFIG_DRM_PANIC_SCREEN, NULL);
1029 	drm_panic_qr_init();
1030 }
1031 
1032 /**
1033  * drm_panic_exit() - Free the resources taken by drm_panic_exit()
1034  */
1035 void drm_panic_exit(void)
1036 {
1037 	drm_panic_qr_exit();
1038 }
1039