8e76a8b384ba142d6967b59e9dc310b4828f60f7
[platform/kernel/linux-starfive.git] / drivers / firmware / efi / libstub / screen_info.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/efi.h>
4 #include <asm/efi.h>
5
6 #include "efistub.h"
7
8 /*
9  * There are two ways of populating the core kernel's struct screen_info via the stub:
10  * - using a configuration table, like below, which relies on the EFI init code
11  *   to locate the table and copy the contents;
12  * - by linking directly to the core kernel's copy of the global symbol.
13  *
14  * The latter is preferred because it makes the EFIFB earlycon available very
15  * early, but it only works if the EFI stub is part of the core kernel image
16  * itself. The zboot decompressor can only use the configuration table
17  * approach.
18  *
19  * In order to support both methods from the same build of the EFI stub
20  * library, provide this dummy global definition of struct screen_info. If it
21  * is required to satisfy a link dependency, it means we need to override the
22  * __weak alloc and free methods with the ones below, and those will be pulled
23  * in as well.
24  */
25 struct screen_info screen_info;
26
27 static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
28
29 struct screen_info *alloc_screen_info(void)
30 {
31         struct screen_info *si;
32         efi_status_t status;
33
34         status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
35                              sizeof(*si), (void **)&si);
36
37         if (status != EFI_SUCCESS)
38                 return NULL;
39
40         status = efi_bs_call(install_configuration_table,
41                              &screen_info_guid, si);
42         if (status == EFI_SUCCESS)
43                 return si;
44
45         efi_bs_call(free_pool, si);
46         return NULL;
47 }
48
49 void free_screen_info(struct screen_info *si)
50 {
51         if (!si)
52                 return;
53
54         efi_bs_call(install_configuration_table, &screen_info_guid, NULL);
55         efi_bs_call(free_pool, si);
56 }