1 /*
2 * efi-dom0.c - Domain0 EFI Boot Support
3 *
4 * Copyright (C) 2016 Shannon Zhao <shannon.zhao@linaro.org>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; If not, see <http://www.gnu.org/licenses/>.
20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23
24 #include "efi.h"
25 #include <xen/sched.h>
26 #include <xen/pfn.h>
27 #include <xen/libfdt/libfdt.h>
28 #include <asm/setup.h>
29 #include <asm/acpi.h>
30 #include "../../../common/decompress.h"
31 #define XZ_EXTERN STATIC
32 #include "../../../common/xz/crc32.c"
33
34 /* Constant to indicate "Xen" in unicode u16 format */
35 static const CHAR16 xen_efi_fw_vendor[] = {0x0058, 0x0065, 0x006E, 0x0000};
36
estimate_efi_size(int mem_nr_banks)37 size_t __init estimate_efi_size(int mem_nr_banks)
38 {
39 size_t size;
40 size_t est_size = sizeof(EFI_SYSTEM_TABLE);
41 size_t ect_size = sizeof(EFI_CONFIGURATION_TABLE);
42 size_t emd_size = sizeof(EFI_MEMORY_DESCRIPTOR);
43 size_t fw_vendor_size = sizeof(xen_efi_fw_vendor);
44 int acpi_mem_nr_banks = 0;
45
46 if ( !acpi_disabled )
47 acpi_mem_nr_banks = bootinfo.acpi.nr_banks;
48
49 size = ROUNDUP(est_size + ect_size + fw_vendor_size, 8);
50 /* plus 1 for new created tables */
51 size += ROUNDUP(emd_size * (mem_nr_banks + acpi_mem_nr_banks + 1), 8);
52
53 return size;
54 }
55
acpi_create_efi_system_table(struct domain * d,struct membank tbl_add[])56 void __init acpi_create_efi_system_table(struct domain *d,
57 struct membank tbl_add[])
58 {
59 u64 table_addr, table_size, offset = 0;
60 u8 *base_ptr;
61 EFI_CONFIGURATION_TABLE *efi_conf_tbl;
62 EFI_SYSTEM_TABLE *efi_sys_tbl;
63
64 table_addr = d->arch.efi_acpi_gpa
65 + acpi_get_table_offset(tbl_add, TBL_EFIT);
66 table_size = sizeof(EFI_SYSTEM_TABLE) + sizeof(EFI_CONFIGURATION_TABLE)
67 + sizeof(xen_efi_fw_vendor);
68 base_ptr = d->arch.efi_acpi_table
69 + acpi_get_table_offset(tbl_add, TBL_EFIT);
70 efi_sys_tbl = (EFI_SYSTEM_TABLE *)base_ptr;
71
72 efi_sys_tbl->Hdr.Signature = EFI_SYSTEM_TABLE_SIGNATURE;
73 /* Specify the revision as 2.5 */
74 efi_sys_tbl->Hdr.Revision = (2 << 16 | 50);
75 efi_sys_tbl->Hdr.HeaderSize = table_size;
76
77 efi_sys_tbl->FirmwareRevision = 1;
78 efi_sys_tbl->NumberOfTableEntries = 1;
79 offset += sizeof(EFI_SYSTEM_TABLE);
80 memcpy(base_ptr + offset, xen_efi_fw_vendor, sizeof(xen_efi_fw_vendor));
81 efi_sys_tbl->FirmwareVendor = (CHAR16 *)(table_addr + offset);
82
83 offset += sizeof(xen_efi_fw_vendor);
84 efi_conf_tbl = (EFI_CONFIGURATION_TABLE *)(base_ptr + offset);
85 efi_conf_tbl->VendorGuid = (EFI_GUID)ACPI_20_TABLE_GUID;
86 efi_conf_tbl->VendorTable = (VOID *)tbl_add[TBL_RSDP].start;
87 efi_sys_tbl->ConfigurationTable = (EFI_CONFIGURATION_TABLE *)(table_addr
88 + offset);
89 xz_crc32_init();
90 efi_sys_tbl->Hdr.CRC32 = xz_crc32((uint8_t *)efi_sys_tbl,
91 efi_sys_tbl->Hdr.HeaderSize, 0);
92
93 tbl_add[TBL_EFIT].start = table_addr;
94 tbl_add[TBL_EFIT].size = table_size;
95 }
96
fill_efi_memory_descriptor(EFI_MEMORY_DESCRIPTOR * desc,UINT32 type,EFI_PHYSICAL_ADDRESS start,UINT64 size)97 static void __init fill_efi_memory_descriptor(EFI_MEMORY_DESCRIPTOR *desc,
98 UINT32 type,
99 EFI_PHYSICAL_ADDRESS start,
100 UINT64 size)
101 {
102 desc->Type = type;
103 desc->PhysicalStart = start;
104 BUG_ON(size & EFI_PAGE_MASK);
105 desc->NumberOfPages = EFI_SIZE_TO_PAGES(size);
106 desc->Attribute = EFI_MEMORY_WB;
107 }
108
acpi_create_efi_mmap_table(struct domain * d,const struct meminfo * mem,struct membank tbl_add[])109 void __init acpi_create_efi_mmap_table(struct domain *d,
110 const struct meminfo *mem,
111 struct membank tbl_add[])
112 {
113 EFI_MEMORY_DESCRIPTOR *desc;
114 unsigned int i;
115 u8 *base_ptr;
116
117 base_ptr = d->arch.efi_acpi_table
118 + acpi_get_table_offset(tbl_add, TBL_MMAP);
119 desc = (EFI_MEMORY_DESCRIPTOR *)base_ptr;
120
121 for ( i = 0; i < mem->nr_banks; i++, desc++ )
122 fill_efi_memory_descriptor(desc, EfiConventionalMemory,
123 mem->bank[i].start, mem->bank[i].size);
124
125 for ( i = 0; i < bootinfo.acpi.nr_banks; i++, desc++ )
126 fill_efi_memory_descriptor(desc, EfiACPIReclaimMemory,
127 bootinfo.acpi.bank[i].start,
128 bootinfo.acpi.bank[i].size);
129
130 fill_efi_memory_descriptor(desc, EfiACPIReclaimMemory,
131 d->arch.efi_acpi_gpa, d->arch.efi_acpi_len);
132
133 tbl_add[TBL_MMAP].start = d->arch.efi_acpi_gpa
134 + acpi_get_table_offset(tbl_add, TBL_MMAP);
135 tbl_add[TBL_MMAP].size = sizeof(EFI_MEMORY_DESCRIPTOR)
136 * (mem->nr_banks + bootinfo.acpi.nr_banks + 1);
137 }
138
139 /* Create /hypervisor/uefi node for efi properties. */
acpi_make_efi_nodes(void * fdt,struct membank tbl_add[])140 int __init acpi_make_efi_nodes(void *fdt, struct membank tbl_add[])
141 {
142 int res;
143
144 res = fdt_begin_node(fdt, "uefi");
145 if ( res )
146 return res;
147
148 res = fdt_property_u64(fdt, "xen,uefi-system-table",
149 tbl_add[TBL_EFIT].start);
150 if ( res )
151 return res;
152
153 res = fdt_property_u64(fdt, "xen,uefi-mmap-start",
154 tbl_add[TBL_MMAP].start);
155 if ( res )
156 return res;
157
158 res = fdt_property_u32(fdt, "xen,uefi-mmap-size",
159 tbl_add[TBL_MMAP].size);
160 if ( res )
161 return res;
162
163 res = fdt_property_u32(fdt, "xen,uefi-mmap-desc-size",
164 sizeof(EFI_MEMORY_DESCRIPTOR));
165 if ( res )
166 return res;
167
168 res = fdt_property_u32(fdt, "xen,uefi-mmap-desc-ver", 1);
169 if ( res )
170 return res;
171
172 res = fdt_end_node(fdt);
173
174 return res;
175 }
176
177 /*
178 * Local variables:
179 * mode: C
180 * c-file-style: "BSD"
181 * c-basic-offset: 4
182 * indent-tabs-mode: nil
183 * End:
184 */
185