tables.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
  4. */
  5. #define LOG_CATEGORY LOGC_ACPI
  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. DECLARE_GLOBAL_DATA_PTR;
  18. /**
  19. * Function prototype to write a specific configuration table
  20. *
  21. * @addr: start address to write the table
  22. * @return: end address of the table
  23. */
  24. typedef ulong (*table_write)(ulong addr);
  25. /**
  26. * struct table_info - Information about each table to write
  27. *
  28. * @name: Name of table (for debugging)
  29. * @write: Function to call to write this table
  30. * @tag: Bloblist tag if using CONFIG_BLOBLIST_TABLES
  31. * @size: Maximum table size
  32. * @align: Table alignment in bytes
  33. */
  34. struct table_info {
  35. const char *name;
  36. table_write write;
  37. enum bloblist_tag_t tag;
  38. int size;
  39. int align;
  40. };
  41. static struct table_info table_list[] = {
  42. #ifdef CONFIG_GENERATE_PIRQ_TABLE
  43. { "pirq", write_pirq_routing_table },
  44. #endif
  45. #ifdef CONFIG_GENERATE_SFI_TABLE
  46. { "sfi", write_sfi_table, },
  47. #endif
  48. #ifdef CONFIG_GENERATE_MP_TABLE
  49. { "mp", write_mp_table, },
  50. #endif
  51. /*
  52. * tables which can go in the bloblist must be last in this list, so
  53. * that the calculation of gd->table_end works properly
  54. */
  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. void table_fill_string(char *dest, const char *src, size_t n, char pad)
  63. {
  64. int start, len;
  65. int i;
  66. strncpy(dest, src, n);
  67. /* Fill the remaining bytes with pad */
  68. len = strlen(src);
  69. start = len < n ? len : n;
  70. for (i = start; i < n; i++)
  71. dest[i] = pad;
  72. }
  73. int write_tables(void)
  74. {
  75. u32 high_table, table_size;
  76. struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1];
  77. bool use_high = false;
  78. u32 rom_addr;
  79. int i;
  80. gd->arch.table_start = ROM_TABLE_ADDR;
  81. rom_addr = gd->arch.table_start;
  82. debug("Writing tables to %x:\n", rom_addr);
  83. for (i = 0; i < ARRAY_SIZE(table_list); i++) {
  84. const struct table_info *table = &table_list[i];
  85. int size = table->size ? : CONFIG_ROM_TABLE_SIZE;
  86. u32 rom_table_end;
  87. if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) {
  88. if (!gd->arch.table_end)
  89. gd->arch.table_end = rom_addr;
  90. rom_addr = (ulong)bloblist_add(table->tag, size,
  91. table->align);
  92. if (!rom_addr)
  93. return log_msg_ret("bloblist", -ENOBUFS);
  94. /* the bloblist is always in high memory */
  95. use_high = true;
  96. if (!gd->arch.table_start_high)
  97. gd->arch.table_start_high = rom_addr;
  98. }
  99. rom_table_end = table->write(rom_addr);
  100. if (!rom_table_end) {
  101. log_err("Can't create configuration table %d\n", i);
  102. return -EINTR;
  103. }
  104. if (IS_ENABLED(CONFIG_SEABIOS)) {
  105. table_size = rom_table_end - rom_addr;
  106. high_table = (u32)(ulong)high_table_malloc(table_size);
  107. if (high_table) {
  108. if (!table->write(high_table)) {
  109. log_err("Can't create configuration table %d\n",
  110. i);
  111. return -EINTR;
  112. }
  113. cfg_tables[i].start = high_table;
  114. cfg_tables[i].size = table_size;
  115. } else {
  116. printf("%d: no memory for configuration tables\n",
  117. i);
  118. return -ENOSPC;
  119. }
  120. }
  121. debug("- wrote '%s' to %x, end %x\n", table->name,
  122. rom_addr, rom_table_end);
  123. if (rom_table_end - rom_addr > size) {
  124. log_err("Out of space for configuration tables: need %x, have %x\n",
  125. rom_table_end - rom_addr, size);
  126. return log_msg_ret("bloblist", -ENOSPC);
  127. }
  128. rom_addr = rom_table_end;
  129. }
  130. if (use_high)
  131. gd->arch.table_end_high = rom_addr;
  132. else
  133. gd->arch.table_end = rom_addr;
  134. if (IS_ENABLED(CONFIG_SEABIOS)) {
  135. /* make sure the last item is zero */
  136. cfg_tables[i].size = 0;
  137. write_coreboot_table(CB_TABLE_ADDR, cfg_tables);
  138. }
  139. if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
  140. void *ptr = (void *)CONFIG_ROM_TABLE_ADDR;
  141. /* Write an RSDP pointing to the tables */
  142. if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
  143. struct acpi_ctx *ctx = gd_acpi_ctx();
  144. acpi_write_rsdp(ptr, ctx->rsdt, ctx->xsdt);
  145. ptr += ALIGN(sizeof(struct acpi_rsdp), 16);
  146. }
  147. if (IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE)) {
  148. void *smbios;
  149. smbios = bloblist_find(BLOBLISTT_SMBIOS_TABLES, 0);
  150. if (!smbios)
  151. return log_msg_ret("smbios", -ENOENT);
  152. memcpy(ptr, smbios, sizeof(struct smbios_entry));
  153. }
  154. }
  155. debug("- done writing tables\n");
  156. return 0;
  157. }