1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> 4 */ 5 6 #include <common.h> 7 #include <bloblist.h> 8 #include <log.h> 9 #include <malloc.h> 10 #include <smbios.h> 11 #include <acpi/acpi_table.h> 12 #include <asm/global_data.h> 13 #include <asm/sfi.h> 14 #include <asm/mpspec.h> 15 #include <asm/tables.h> 16 #include <asm/coreboot_tables.h> 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 /** 21 * Function prototype to write a specific configuration table 22 * 23 * @addr: start address to write the table 24 * @return: end address of the table 25 */ 26 typedef ulong (*table_write)(ulong addr); 27 28 /** 29 * struct table_info - Information about each table to write 30 * 31 * @name: Name of table (for debugging) 32 * @write: Function to call to write this table 33 * @tag: Bloblist tag if using CONFIG_BLOBLIST_TABLES 34 * @size: Maximum table size 35 * @align: Table alignment in bytes 36 */ 37 struct table_info { 38 const char *name; 39 table_write write; 40 enum bloblist_tag_t tag; 41 int size; 42 int align; 43 }; 44 45 static struct table_info table_list[] = { 46 #ifdef CONFIG_GENERATE_PIRQ_TABLE 47 { "pirq", write_pirq_routing_table }, 48 #endif 49 #ifdef CONFIG_GENERATE_SFI_TABLE 50 { "sfi", write_sfi_table, }, 51 #endif 52 #ifdef CONFIG_GENERATE_MP_TABLE 53 { "mp", write_mp_table, }, 54 #endif 55 #ifdef CONFIG_GENERATE_ACPI_TABLE 56 { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, 57 #endif 58 #ifdef CONFIG_GENERATE_SMBIOS_TABLE 59 { "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100}, 60 #endif 61 }; 62 63 void table_fill_string(char *dest, const char *src, size_t n, char pad) 64 { 65 int start, len; 66 int i; 67 68 strncpy(dest, src, n); 69 70 /* Fill the remaining bytes with pad */ 71 len = strlen(src); 72 start = len < n ? len : n; 73 for (i = start; i < n; i++) 74 dest[i] = pad; 75 } 76 77 int write_tables(void) 78 { 79 u32 rom_table_start; 80 u32 rom_table_end; 81 u32 high_table, table_size; 82 struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; 83 int i; 84 85 rom_table_start = ROM_TABLE_ADDR; 86 87 debug("Writing tables to %x:\n", rom_table_start); assignCastvigra::detail::ExecLoop88 for (i = 0; i < ARRAY_SIZE(table_list); i++) { 89 const struct table_info *table = &table_list[i]; 90 int size = table->size ? : CONFIG_ROM_TABLE_SIZE; 91 92 if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) { 93 rom_table_start = (ulong)bloblist_add(table->tag, size, 94 table->align); 95 if (!rom_table_start) 96 return log_msg_ret("bloblist", -ENOBUFS); 97 } 98 rom_table_end = table->write(rom_table_start); 99 rom_table_end = ALIGN(rom_table_end, ROM_TABLE_ALIGN); 100 101 if (IS_ENABLED(CONFIG_SEABIOS)) { 102 table_size = rom_table_end - rom_table_start; 103 high_table = (u32)(ulong)high_table_malloc(table_size); 104 if (high_table) { 105 table->write(high_table); 106 107 cfg_tables[i].start = high_table; 108 cfg_tables[i].size = table_size; notEqualvigra::detail::ExecLoop109 } else { 110 printf("%d: no memory for configuration tables\n", 111 i); 112 return -ENOSPC; 113 } 114 } 115 116 debug("- wrote '%s' to %x, end %x\n", table->name, 117 rom_table_start, rom_table_end); 118 if (rom_table_end - rom_table_start > size) { dotvigra::detail::ExecLoop119 log_err("Out of space for configuration tables: need %x, have %x\n", 120 rom_table_end - rom_table_start, size); 121 return log_msg_ret("bloblist", -ENOSPC); 122 } 123 rom_table_start = rom_table_end; 124 } 125 126 if (IS_ENABLED(CONFIG_SEABIOS)) { 127 /* make sure the last item is zero */ 128 cfg_tables[i].size = 0; dotvigra::detail::ExecLoop129 write_coreboot_table(CB_TABLE_ADDR, cfg_tables); 130 } 131 132 if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) { 133 void *ptr = (void *)CONFIG_ROM_TABLE_ADDR; 134 135 /* Write an RSDP pointing to the tables */ 136 if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { 137 struct acpi_ctx *ctx = gd_acpi_ctx(); 138 squaredNormvigra::detail::ExecLoop139 acpi_write_rsdp(ptr, ctx->rsdt, ctx->xsdt); 140 ptr += ALIGN(sizeof(struct acpi_rsdp), 16); 141 } 142 if (IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE)) { 143 void *smbios; 144 145 smbios = bloblist_find(BLOBLISTT_SMBIOS_TABLES, 0); 146 if (!smbios) 147 return log_msg_ret("smbios", -ENOENT); 148 memcpy(ptr, smbios, sizeof(struct smbios_entry)); 149 } 150 } 151 152 debug("- done writing tables\n"); dotvigra::detail::UnrollDot153 154 return 0; 155 } 156