xref: /linux/drivers/firmware/efi/libstub/primary_display.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1*c5a8f13fSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0
2*c5a8f13fSThomas Zimmermann 
3*c5a8f13fSThomas Zimmermann #include <linux/efi.h>
4*c5a8f13fSThomas Zimmermann #include <linux/sysfb.h>
5*c5a8f13fSThomas Zimmermann 
6*c5a8f13fSThomas Zimmermann #include <asm/efi.h>
7*c5a8f13fSThomas Zimmermann 
8*c5a8f13fSThomas Zimmermann #include "efistub.h"
9*c5a8f13fSThomas Zimmermann 
10*c5a8f13fSThomas Zimmermann /*
11*c5a8f13fSThomas Zimmermann  * There are two ways of populating the core kernel's sysfb_primary_display
12*c5a8f13fSThomas Zimmermann  * via the stub:
13*c5a8f13fSThomas Zimmermann  *
14*c5a8f13fSThomas Zimmermann  *   - using a configuration table, which relies on the EFI init code to
15*c5a8f13fSThomas Zimmermann  *     locate the table and copy the contents; or
16*c5a8f13fSThomas Zimmermann  *
17*c5a8f13fSThomas Zimmermann  *   - by linking directly to the core kernel's copy of the global symbol.
18*c5a8f13fSThomas Zimmermann  *
19*c5a8f13fSThomas Zimmermann  * The latter is preferred because it makes the EFIFB earlycon available very
20*c5a8f13fSThomas Zimmermann  * early, but it only works if the EFI stub is part of the core kernel image
21*c5a8f13fSThomas Zimmermann  * itself. The zboot decompressor can only use the configuration table
22*c5a8f13fSThomas Zimmermann  * approach.
23*c5a8f13fSThomas Zimmermann  */
24*c5a8f13fSThomas Zimmermann 
25*c5a8f13fSThomas Zimmermann static efi_guid_t primary_display_guid = LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID;
26*c5a8f13fSThomas Zimmermann 
27*c5a8f13fSThomas Zimmermann struct sysfb_display_info *__alloc_primary_display(void)
28*c5a8f13fSThomas Zimmermann {
29*c5a8f13fSThomas Zimmermann 	struct sysfb_display_info *dpy;
30*c5a8f13fSThomas Zimmermann 	efi_status_t status;
31*c5a8f13fSThomas Zimmermann 
32*c5a8f13fSThomas Zimmermann 	status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
33*c5a8f13fSThomas Zimmermann 			     sizeof(*dpy), (void **)&dpy);
34*c5a8f13fSThomas Zimmermann 
35*c5a8f13fSThomas Zimmermann 	if (status != EFI_SUCCESS)
36*c5a8f13fSThomas Zimmermann 		return NULL;
37*c5a8f13fSThomas Zimmermann 
38*c5a8f13fSThomas Zimmermann 	memset(dpy, 0, sizeof(*dpy));
39*c5a8f13fSThomas Zimmermann 
40*c5a8f13fSThomas Zimmermann 	status = efi_bs_call(install_configuration_table,
41*c5a8f13fSThomas Zimmermann 			     &primary_display_guid, dpy);
42*c5a8f13fSThomas Zimmermann 	if (status == EFI_SUCCESS)
43*c5a8f13fSThomas Zimmermann 		return dpy;
44*c5a8f13fSThomas Zimmermann 
45*c5a8f13fSThomas Zimmermann 	efi_bs_call(free_pool, dpy);
46*c5a8f13fSThomas Zimmermann 	return NULL;
47*c5a8f13fSThomas Zimmermann }
48*c5a8f13fSThomas Zimmermann 
49*c5a8f13fSThomas Zimmermann void free_primary_display(struct sysfb_display_info *dpy)
50*c5a8f13fSThomas Zimmermann {
51*c5a8f13fSThomas Zimmermann 	if (!dpy)
52*c5a8f13fSThomas Zimmermann 		return;
53*c5a8f13fSThomas Zimmermann 
54*c5a8f13fSThomas Zimmermann 	efi_bs_call(install_configuration_table, &primary_display_guid, NULL);
55*c5a8f13fSThomas Zimmermann 	efi_bs_call(free_pool, dpy);
56*c5a8f13fSThomas Zimmermann }
57