2 * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
4 * SPDX-License-Identifier: GPL-2.0+
13 #include <asm/tables.h>
15 #include <linux/list.h>
19 * This function allocates memory for ACPI tables
21 * @entry : BIOS linker command entry which tells where to allocate memory
22 * (either high memory or low memory)
23 * @addr : The address that should be used for low memory allcation. If the
24 * memory allocation request is 'ZONE_HIGH' then this parameter will
26 * @return: 0 on success, or negative value on failure
28 static int bios_linker_allocate(struct bios_linker_entry *entry, u32 *addr)
32 unsigned long aligned_addr;
34 align = le32_to_cpu(entry->alloc.align);
35 /* align must be power of 2 */
36 if (align & (align - 1)) {
37 printf("error: wrong alignment %u\n", align);
41 file = qemu_fwcfg_find_file(entry->alloc.file);
43 printf("error: can't find file %s\n", entry->alloc.file);
47 size = be32_to_cpu(file->cfg.size);
50 * ZONE_HIGH means we need to allocate from high memory, since
51 * malloc space is already at the end of RAM, so we directly use it.
52 * If allocation zone is ZONE_FSEG, then we use the 'addr' passed
53 * in which is low memory
55 if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
56 aligned_addr = (unsigned long)memalign(align, size);
58 printf("error: allocating resource\n");
61 } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
62 aligned_addr = ALIGN(*addr, align);
64 printf("error: invalid allocation zone\n");
68 debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
69 file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
71 qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
72 size, (void *)aligned_addr);
73 file->addr = aligned_addr;
75 /* adjust address for low memory allocation */
76 if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
77 *addr = (aligned_addr + size);
83 * This function patches ACPI tables previously loaded
84 * by bios_linker_allocate()
86 * @entry : BIOS linker command entry which tells how to patch
88 * @return: 0 on success, or negative value on failure
90 static int bios_linker_add_pointer(struct bios_linker_entry *entry)
92 struct fw_file *dest, *src;
93 uint32_t offset = le32_to_cpu(entry->pointer.offset);
96 dest = qemu_fwcfg_find_file(entry->pointer.dest_file);
97 if (!dest || !dest->addr)
99 src = qemu_fwcfg_find_file(entry->pointer.src_file);
100 if (!src || !src->addr)
103 debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
104 dest->addr, src->addr, offset, entry->pointer.size, pointer);
106 memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
107 pointer = le64_to_cpu(pointer);
108 pointer += (unsigned long)src->addr;
109 pointer = cpu_to_le64(pointer);
110 memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
116 * This function updates checksum fields of ACPI tables previously loaded
117 * by bios_linker_allocate()
119 * @entry : BIOS linker command entry which tells where to update ACPI table
121 * @return: 0 on success, or negative value on failure
123 static int bios_linker_add_checksum(struct bios_linker_entry *entry)
125 struct fw_file *file;
126 uint8_t *data, cksum = 0;
127 uint8_t *cksum_start;
129 file = qemu_fwcfg_find_file(entry->cksum.file);
130 if (!file || !file->addr)
133 data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
134 cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
135 cksum = table_compute_checksum(cksum_start,
136 le32_to_cpu(entry->cksum.length));
142 unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
145 entries[0].size = ISA_START_ADDRESS;
146 entries[0].type = E820_RAM;
148 entries[1].addr = ISA_START_ADDRESS;
149 entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
150 entries[1].type = E820_RESERVED;
153 * since we use memalign(malloc) to allocate high memory for
154 * storing ACPI tables, we need to reserve them in e820 tables,
155 * otherwise kernel will reclaim them and data will be corrupted
157 entries[2].addr = ISA_END_ADDRESS;
158 entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
159 entries[2].type = E820_RAM;
161 /* for simplicity, reserve entire malloc space */
162 entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
163 entries[3].size = TOTAL_MALLOC_LEN;
164 entries[3].type = E820_RESERVED;
166 entries[4].addr = gd->relocaddr;
167 entries[4].size = gd->ram_size - gd->relocaddr;
168 entries[4].type = E820_RESERVED;
170 entries[5].addr = CONFIG_PCIE_ECAM_BASE;
171 entries[5].size = CONFIG_PCIE_ECAM_SIZE;
172 entries[5].type = E820_RESERVED;
177 /* This function loads and patches ACPI tables provided by QEMU */
178 u32 write_acpi_tables(u32 addr)
181 struct fw_file *file;
182 struct bios_linker_entry *table_loader;
183 struct bios_linker_entry *entry;
186 /* make sure fw_list is loaded */
187 ret = qemu_fwcfg_read_firmware_list();
189 printf("error: can't read firmware file list\n");
193 file = qemu_fwcfg_find_file("etc/table-loader");
195 printf("error: can't find etc/table-loader\n");
199 size = be32_to_cpu(file->cfg.size);
200 if ((size % sizeof(*entry)) != 0) {
201 printf("error: table-loader maybe corrupted\n");
205 table_loader = malloc(size);
207 printf("error: no memory for table-loader\n");
211 qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
214 for (i = 0; i < (size / sizeof(*entry)); i++) {
215 entry = table_loader + i;
216 switch (le32_to_cpu(entry->command)) {
217 case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
218 ret = bios_linker_allocate(entry, &addr);
222 case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
223 ret = bios_linker_add_pointer(entry);
227 case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
228 ret = bios_linker_add_checksum(entry);
239 struct fw_cfg_file_iter iter;
240 for (file = qemu_fwcfg_file_iter_init(&iter);
241 !qemu_fwcfg_file_iter_end(&iter);
242 file = qemu_fwcfg_file_iter_next(&iter)) {
244 free((void *)file->addr);