coreboot_table.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <drivers/coreboot/cbmem_console.h>
  9. #include <common/debug.h>
  10. #include <lib/coreboot.h>
  11. #include <lib/mmio.h>
  12. #include <lib/xlat_tables/xlat_tables_v2.h>
  13. /*
  14. * Structures describing coreboot's in-memory descriptor tables. See
  15. * <coreboot>/src/commonlib/include/commonlib/coreboot_tables.h for
  16. * canonical implementation.
  17. */
  18. typedef struct {
  19. char signature[4];
  20. uint32_t header_bytes;
  21. uint32_t header_checksum;
  22. uint32_t table_bytes;
  23. uint32_t table_checksum;
  24. uint32_t table_entries;
  25. } cb_header_t;
  26. typedef enum {
  27. CB_TAG_MEMORY = 0x1,
  28. CB_TAG_SERIAL = 0xf,
  29. CB_TAG_CBMEM_CONSOLE = 0x17,
  30. } cb_tag_t;
  31. typedef struct {
  32. uint32_t tag;
  33. uint32_t size;
  34. union {
  35. coreboot_memrange_t memranges[COREBOOT_MAX_MEMRANGES];
  36. coreboot_serial_t serial;
  37. uint64_t uint64;
  38. };
  39. } cb_entry_t;
  40. coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES];
  41. coreboot_serial_t coreboot_serial;
  42. uint64_t coreboot_table_addr;
  43. uint32_t coreboot_table_size;
  44. /*
  45. * The coreboot table is parsed before the MMU is enabled (i.e. with strongly
  46. * ordered memory), so we cannot make unaligned accesses. The table entries
  47. * immediately follow one another without padding, so nothing after the header
  48. * is guaranteed to be naturally aligned. Therefore, we need to define safety
  49. * functions that can read unaligned integers.
  50. */
  51. static uint32_t read_le32(uint32_t *p)
  52. {
  53. uintptr_t addr = (uintptr_t)p;
  54. return mmio_read_8(addr) |
  55. mmio_read_8(addr + 1) << 8 |
  56. mmio_read_8(addr + 2) << 16 |
  57. mmio_read_8(addr + 3) << 24;
  58. }
  59. static uint64_t read_le64(uint64_t *p)
  60. {
  61. return read_le32((void *)p) | (uint64_t)read_le32((void *)p + 4) << 32;
  62. }
  63. static void expand_and_mmap(uintptr_t baseaddr, size_t size)
  64. {
  65. uintptr_t pageaddr = round_down(baseaddr, PAGE_SIZE);
  66. size_t expanded = round_up(baseaddr - pageaddr + size, PAGE_SIZE);
  67. mmap_add_region(pageaddr, pageaddr, expanded,
  68. MT_MEMORY | MT_RW | MT_NS | MT_EXECUTE_NEVER);
  69. }
  70. static void setup_cbmem_console(uintptr_t baseaddr)
  71. {
  72. static console_cbmc_t console;
  73. assert(!console.console.base); /* should only have one CBMEM console */
  74. /* CBMEM console structure stores its size in first header field. */
  75. uint32_t size = *(uint32_t *)baseaddr;
  76. expand_and_mmap(baseaddr, size);
  77. console_cbmc_register(baseaddr, &console);
  78. console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
  79. CONSOLE_FLAG_RUNTIME |
  80. CONSOLE_FLAG_CRASH);
  81. }
  82. coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size)
  83. {
  84. int i;
  85. for (i = 0; i < COREBOOT_MAX_MEMRANGES; i++) {
  86. coreboot_memrange_t *range = &coreboot_memranges[i];
  87. if (range->type == CB_MEM_NONE)
  88. break; /* end of table reached */
  89. if ((start >= range->start) &&
  90. (start - range->start < range->size) &&
  91. (size <= range->size - (start - range->start))) {
  92. return range->type;
  93. }
  94. }
  95. return CB_MEM_NONE;
  96. }
  97. void coreboot_get_table_location(uint64_t *address, uint32_t *size)
  98. {
  99. *address = coreboot_table_addr;
  100. *size = coreboot_table_size;
  101. }
  102. void coreboot_table_setup(void *base)
  103. {
  104. cb_header_t *header = base;
  105. void *ptr;
  106. int i;
  107. if (strncmp(header->signature, "LBIO", 4)) {
  108. ERROR("coreboot table signature corrupt!\n");
  109. return;
  110. }
  111. coreboot_table_addr = (uint64_t) base;
  112. coreboot_table_size = header->header_bytes + header->table_bytes;
  113. ptr = base + header->header_bytes;
  114. for (i = 0; i < header->table_entries; i++) {
  115. size_t size;
  116. cb_entry_t *entry = ptr;
  117. if (ptr - base >= header->header_bytes + header->table_bytes) {
  118. ERROR("coreboot table exceeds its bounds!\n");
  119. break;
  120. }
  121. switch (read_le32(&entry->tag)) {
  122. case CB_TAG_MEMORY:
  123. size = read_le32(&entry->size) -
  124. offsetof(cb_entry_t, memranges);
  125. if (size > sizeof(coreboot_memranges)) {
  126. ERROR("Need to truncate coreboot memranges!\n");
  127. size = sizeof(coreboot_memranges);
  128. }
  129. memcpy(&coreboot_memranges, &entry->memranges, size);
  130. break;
  131. case CB_TAG_SERIAL:
  132. memcpy(&coreboot_serial, &entry->serial,
  133. sizeof(coreboot_serial));
  134. break;
  135. case CB_TAG_CBMEM_CONSOLE:
  136. setup_cbmem_console(read_le64(&entry->uint64));
  137. break;
  138. default:
  139. /* There are many tags TF doesn't need to care about. */
  140. break;
  141. }
  142. ptr += read_le32(&entry->size);
  143. }
  144. }