cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opal.c (2284B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) 2016 IBM Corporation.
      4 */
      5
      6#include "ops.h"
      7#include "stdio.h"
      8#include "io.h"
      9#include <libfdt.h>
     10#include "../include/asm/opal-api.h"
     11
     12/* Global OPAL struct used by opal-call.S */
     13struct opal {
     14	u64 base;
     15	u64 entry;
     16} opal;
     17
     18static u32 opal_con_id;
     19
     20/* see opal-wrappers.S */
     21int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer);
     22int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer);
     23int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length);
     24int64_t opal_console_flush(uint64_t term_number);
     25int64_t opal_poll_events(uint64_t *outstanding_event_mask);
     26
     27void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr);
     28
     29static int opal_con_open(void)
     30{
     31	/*
     32	 * When OPAL loads the boot kernel it stashes the OPAL base and entry
     33	 * address in r8 and r9 so the kernel can use the OPAL console
     34	 * before unflattening the devicetree. While executing the wrapper will
     35	 * probably trash r8 and r9 so this kentry hook restores them before
     36	 * entering the decompressed kernel.
     37	 */
     38	platform_ops.kentry = opal_kentry;
     39	return 0;
     40}
     41
     42static void opal_con_putc(unsigned char c)
     43{
     44	int64_t rc;
     45	uint64_t olen, len;
     46
     47	do {
     48		rc = opal_console_write_buffer_space(opal_con_id, &olen);
     49		len = be64_to_cpu(olen);
     50		if (rc)
     51			return;
     52		opal_poll_events(NULL);
     53	} while (len < 1);
     54
     55
     56	olen = cpu_to_be64(1);
     57	opal_console_write(opal_con_id, &olen, &c);
     58}
     59
     60static void opal_con_close(void)
     61{
     62	opal_console_flush(opal_con_id);
     63}
     64
     65static void opal_init(void)
     66{
     67	void *opal_node;
     68
     69	opal_node = finddevice("/ibm,opal");
     70	if (!opal_node)
     71		return;
     72	if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0)
     73		return;
     74	opal.base = be64_to_cpu(opal.base);
     75	if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0)
     76		return;
     77	opal.entry = be64_to_cpu(opal.entry);
     78}
     79
     80int opal_console_init(void *devp, struct serial_console_data *scdp)
     81{
     82	opal_init();
     83
     84	if (devp) {
     85		int n = getprop(devp, "reg", &opal_con_id, sizeof(u32));
     86		if (n != sizeof(u32))
     87			return -1;
     88		opal_con_id = be32_to_cpu(opal_con_id);
     89	} else
     90		opal_con_id = 0;
     91
     92	scdp->open = opal_con_open;
     93	scdp->putc = opal_con_putc;
     94	scdp->close = opal_con_close;
     95
     96	return 0;
     97}