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