2 * Copyright (C) 2013 Intel Corporation; author Matt Fleming
4 * This file is part of the Linux kernel, and is made available under
5 * the terms of the GNU General Public License version 2.
8 #include <linux/console.h>
10 #include <linux/font.h>
12 #include <linux/kernel.h>
13 #include <asm/setup.h>
15 static const struct font_desc
*font
;
16 static u32 efi_x
, efi_y
;
18 static bool early_efi_keep
;
21 * efi earlyprintk need use early_ioremap to map the framebuffer.
22 * But early_ioremap is not usable for earlyprintk=efi,keep, ioremap should
23 * be used instead. ioremap will be available after paging_init() which is
24 * earlier than initcall callbacks. Thus adding this early initcall function
25 * early_efi_map_fb to map the whole efi framebuffer.
27 static __init
int early_efi_map_fb(void)
29 unsigned long base
, size
;
34 base
= boot_params
.screen_info
.lfb_base
;
35 size
= boot_params
.screen_info
.lfb_size
;
36 efi_fb
= ioremap(base
, size
);
38 return efi_fb
? 0 : -ENOMEM
;
40 early_initcall(early_efi_map_fb
);
43 * early_efi_map maps efi framebuffer region [start, start + len -1]
44 * In case earlyprintk=efi,keep we have the whole framebuffer mapped already
45 * so just return the offset efi_fb + start.
47 static __ref
void *early_efi_map(unsigned long start
, unsigned long len
)
51 base
= boot_params
.screen_info
.lfb_base
;
54 return (efi_fb
+ start
);
56 return early_ioremap(base
+ start
, len
);
59 static __ref
void early_efi_unmap(void *addr
, unsigned long len
)
62 early_iounmap(addr
, len
);
65 static void early_efi_clear_scanline(unsigned int y
)
70 len
= boot_params
.screen_info
.lfb_linelength
;
71 dst
= early_efi_map(y
*len
, len
);
76 early_efi_unmap(dst
, len
);
79 static void early_efi_scroll_up(void)
81 unsigned long *dst
, *src
;
85 len
= boot_params
.screen_info
.lfb_linelength
;
86 height
= boot_params
.screen_info
.lfb_height
;
88 for (i
= 0; i
< height
- font
->height
; i
++) {
89 dst
= early_efi_map(i
*len
, len
);
93 src
= early_efi_map((i
+ font
->height
) * len
, len
);
95 early_efi_unmap(dst
, len
);
99 memmove(dst
, src
, len
);
101 early_efi_unmap(src
, len
);
102 early_efi_unmap(dst
, len
);
106 static void early_efi_write_char(u32
*dst
, unsigned char c
, unsigned int h
)
108 const u32 color_black
= 0x00000000;
109 const u32 color_white
= 0x00ffffff;
114 src
= font
->data
+ c
* font
->height
;
117 for (m
= 0; m
< 8; m
++) {
118 if ((s8
>> (7 - m
)) & 1)
127 early_efi_write(struct console
*con
, const char *str
, unsigned int num
)
129 struct screen_info
*si
;
134 si
= &boot_params
.screen_info
;
135 len
= si
->lfb_linelength
;
138 unsigned int linemax
;
139 unsigned int h
, count
= 0;
141 for (s
= str
; *s
&& *s
!= '\n'; s
++) {
147 linemax
= (si
->lfb_width
- efi_x
) / font
->width
;
151 for (h
= 0; h
< font
->height
; h
++) {
154 dst
= early_efi_map((efi_y
+ h
) * len
, len
);
163 early_efi_write_char(dst
+ x
*4, *s
, h
);
168 early_efi_unmap(dst
, len
);
172 efi_x
+= count
* font
->width
;
175 if (num
> 0 && *s
== '\n') {
177 efi_y
+= font
->height
;
182 if (efi_x
>= si
->lfb_width
) {
184 efi_y
+= font
->height
;
187 if (efi_y
+ font
->height
> si
->lfb_height
) {
190 efi_y
-= font
->height
;
191 early_efi_scroll_up();
193 for (i
= 0; i
< font
->height
; i
++)
194 early_efi_clear_scanline(efi_y
+ i
);
199 static __init
int early_efi_setup(struct console
*con
, char *options
)
201 struct screen_info
*si
;
205 si
= &boot_params
.screen_info
;
206 xres
= si
->lfb_width
;
207 yres
= si
->lfb_height
;
210 * early_efi_write_char() implicitly assumes a framebuffer with
213 if (si
->lfb_depth
!= 32)
216 font
= get_default_font(xres
, yres
, -1, -1);
220 efi_y
= rounddown(yres
, font
->height
) - font
->height
;
221 for (i
= 0; i
< (yres
- efi_y
) / font
->height
; i
++)
222 early_efi_scroll_up();
224 /* early_console_register will unset CON_BOOT in case ,keep */
225 if (!(con
->flags
& CON_BOOT
))
226 early_efi_keep
= true;
230 struct console early_efi_console
= {
232 .write
= early_efi_write
,
233 .setup
= early_efi_setup
,
234 .flags
= CON_PRINTBUFFER
,