1/* 2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <asm_macros.S> 8#include <console_macros.S> 9#include <drivers/coreboot/cbmem_console.h> 10 11/* 12 * This driver implements access to coreboot's in-memory console 13 * (CBMEM console). For the original implementation, see 14 * <coreboot>/src/lib/cbmem_console.c. 15 */ 16 17 .globl console_cbmc_register 18 .globl console_cbmc_putc 19 .globl console_cbmc_flush 20 21 /* ----------------------------------------------- 22 * int console_cbmc_register(uintptr_t base, 23 * console_cbmc_t *console); 24 * Registers a new CBMEM console instance. Reads 25 * the size field from the buffer header structure 26 * and stores it in our console_cbmc_t struct, so 27 * that we keep the size in secure memory where we 28 * can trust it. A malicious EL1 could manipulate 29 * the console buffer (including the header), so we 30 * must not trust its contents after boot. 31 * In: x0 - CBMEM console base address 32 * x1 - pointer to empty console_cbmc_t struct 33 * Out: x0 - 1 to indicate success 34 * Clobber list: x0, x1, x2, x7 35 * ----------------------------------------------- 36 */ 37func console_cbmc_register 38 str x0, [x1, #CONSOLE_T_BASE] 39 ldr w2, [x0] 40 str w2, [x1, #CONSOLE_T_CBMC_SIZE] 41 mov x0, x1 42 finish_console_register cbmc putc=1, flush=1 43endfunc console_cbmc_register 44 45 /* ----------------------------------------------- 46 * int console_cbmc_puts(int c, console_cbmc_t *console) 47 * Writes a character to the CBMEM console buffer, 48 * including overflow handling of the cursor field. 49 * The character must be preserved in x0. 50 * In: x0 - character to be stored 51 * x1 - pointer to console_cbmc_t struct 52 * Clobber list: x1, x2, x16, x17 53 * ----------------------------------------------- 54 */ 55func console_cbmc_putc 56 ldr w2, [x1, #CONSOLE_T_CBMC_SIZE] 57 ldr x1, [x1, #CONSOLE_T_BASE] 58 add x1, x1, #8 /* keep address of body in x1 */ 59 60 ldr w16, [x1, #-4] /* load cursor (one u32 before body) */ 61 and w17, w16, #0xf0000000 /* keep flags part in w17 */ 62 and w16, w16, #0x0fffffff /* keep actual cursor part in w16 */ 63 64 cmp w16, w2 /* sanity check that cursor < size */ 65 b.lo putc_within_bounds 66 mov w0, #-1 /* cursor >= size must be malicious */ 67 ret /* so return error, don't write char */ 68 69putc_within_bounds: 70 strb w0, [x1, w16, uxtw] /* body[cursor] = character */ 71 add w16, w16, #1 /* cursor++ */ 72 cmp w16, w2 /* if cursor < size... */ 73 b.lo putc_write_back /* ...skip overflow handling */ 74 75 mov w16, #0 /* on overflow, set cursor back to 0 */ 76 orr w17, w17, #(1 << 31) /* and set overflow flag */ 77 78putc_write_back: 79 orr w16, w16, w17 /* merge cursor and flags back */ 80 str w16, [x1, #-4] /* write back cursor to memory */ 81 ret 82endfunc console_cbmc_putc 83 84 /* ----------------------------------------------- 85 * void console_cbmc_flush(console_cbmc_t *console) 86 * Flushes the CBMEM console by flushing the 87 * console buffer from the CPU's data cache. 88 * In: x0 - pointer to console_cbmc_t struct 89 * Out: void 90 * Clobber list: x0, x1, x2, x3 91 * ----------------------------------------------- 92 */ 93func console_cbmc_flush 94 ldr x1, [x0, #CONSOLE_T_CBMC_SIZE] 95 ldr x0, [x0, #CONSOLE_T_BASE] 96 add x1, x1, #8 /* add size of console header */ 97 b clean_dcache_range /* (clobbers x2 and x3) */ 98endfunc console_cbmc_flush 99