cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

tc58128.c (5676B)


      1/*
      2 * TC58128 NAND EEPROM emulation
      3 *
      4 * Copyright (c) 2005 Samuel Tardieu
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice (including the next
     14 * paragraph) shall be included in all copies or substantial portions of the
     15 * Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 *
     25 * SPDX-License-Identifier: MIT
     26 */
     27#include "qemu/osdep.h"
     28#include "qemu/units.h"
     29#include "hw/sh4/sh.h"
     30#include "hw/loader.h"
     31#include "sysemu/qtest.h"
     32#include "qemu/error-report.h"
     33
     34#define CE1  0x0100
     35#define CE2  0x0200
     36#define RE   0x0400
     37#define WE   0x0800
     38#define ALE  0x1000
     39#define CLE  0x2000
     40#define RDY1 0x4000
     41#define RDY2 0x8000
     42#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
     43
     44typedef enum { WAIT, READ1, READ2, READ3 } state_t;
     45
     46typedef struct {
     47    uint8_t *flash_contents;
     48    state_t state;
     49    uint32_t address;
     50    uint8_t address_cycle;
     51} tc58128_dev;
     52
     53static tc58128_dev tc58128_devs[2];
     54
     55#define FLASH_SIZE (16 * MiB)
     56
     57static void init_dev(tc58128_dev * dev, const char *filename)
     58{
     59    int ret, blocks;
     60
     61    dev->state = WAIT;
     62    dev->flash_contents = g_malloc(FLASH_SIZE);
     63    memset(dev->flash_contents, 0xff, FLASH_SIZE);
     64    if (filename) {
     65	/* Load flash image skipping the first block */
     66        ret = load_image_size(filename, dev->flash_contents + 528 * 32,
     67                              FLASH_SIZE - 528 * 32);
     68	if (ret < 0) {
     69            if (!qtest_enabled()) {
     70                error_report("Could not load flash image %s", filename);
     71                exit(1);
     72            }
     73	} else {
     74	    /* Build first block with number of blocks */
     75            blocks = DIV_ROUND_UP(ret, 528 * 32);
     76	    dev->flash_contents[0] = blocks & 0xff;
     77	    dev->flash_contents[1] = (blocks >> 8) & 0xff;
     78	    dev->flash_contents[2] = (blocks >> 16) & 0xff;
     79	    dev->flash_contents[3] = (blocks >> 24) & 0xff;
     80	    fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
     81		    filename);
     82	}
     83    }
     84}
     85
     86static void handle_command(tc58128_dev * dev, uint8_t command)
     87{
     88    switch (command) {
     89    case 0xff:
     90	fprintf(stderr, "reset flash device\n");
     91	dev->state = WAIT;
     92	break;
     93    case 0x00:
     94	fprintf(stderr, "read mode 1\n");
     95	dev->state = READ1;
     96	dev->address_cycle = 0;
     97	break;
     98    case 0x01:
     99	fprintf(stderr, "read mode 2\n");
    100	dev->state = READ2;
    101	dev->address_cycle = 0;
    102	break;
    103    case 0x50:
    104	fprintf(stderr, "read mode 3\n");
    105	dev->state = READ3;
    106	dev->address_cycle = 0;
    107	break;
    108    default:
    109	fprintf(stderr, "unknown flash command 0x%02x\n", command);
    110        abort();
    111    }
    112}
    113
    114static void handle_address(tc58128_dev * dev, uint8_t data)
    115{
    116    switch (dev->state) {
    117    case READ1:
    118    case READ2:
    119    case READ3:
    120	switch (dev->address_cycle) {
    121	case 0:
    122	    dev->address = data;
    123	    if (dev->state == READ2)
    124		dev->address |= 0x100;
    125	    else if (dev->state == READ3)
    126		dev->address |= 0x200;
    127	    break;
    128	case 1:
    129	    dev->address += data * 528 * 0x100;
    130	    break;
    131	case 2:
    132	    dev->address += data * 528;
    133	    fprintf(stderr, "address pointer in flash: 0x%08x\n",
    134		    dev->address);
    135	    break;
    136	default:
    137	    /* Invalid data */
    138            abort();
    139	}
    140	dev->address_cycle++;
    141	break;
    142    default:
    143        abort();
    144    }
    145}
    146
    147static uint8_t handle_read(tc58128_dev * dev)
    148{
    149#if 0
    150    if (dev->address % 0x100000 == 0)
    151	fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
    152#endif
    153    return dev->flash_contents[dev->address++];
    154}
    155
    156/* We never mark the device as busy, so interrupts cannot be triggered
    157   XXXXX */
    158
    159static int tc58128_cb(uint16_t porta, uint16_t portb,
    160                      uint16_t * periph_pdtra, uint16_t * periph_portadir,
    161                      uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
    162{
    163    int dev;
    164
    165    if ((porta & CE1) == 0)
    166	dev = 0;
    167    else if ((porta & CE2) == 0)
    168	dev = 1;
    169    else
    170	return 0;		/* No device selected */
    171
    172    if ((porta & RE) && (porta & WE)) {
    173	/* Nothing to do, assert ready and return to input state */
    174	*periph_portadir &= 0xff00;
    175	*periph_portadir |= RDY(dev);
    176	*periph_pdtra |= RDY(dev);
    177	return 1;
    178    }
    179
    180    if (porta & CLE) {
    181	/* Command */
    182	assert((porta & WE) == 0);
    183	handle_command(&tc58128_devs[dev], porta & 0x00ff);
    184    } else if (porta & ALE) {
    185	assert((porta & WE) == 0);
    186	handle_address(&tc58128_devs[dev], porta & 0x00ff);
    187    } else if ((porta & RE) == 0) {
    188	*periph_portadir |= 0x00ff;
    189	*periph_pdtra &= 0xff00;
    190	*periph_pdtra |= handle_read(&tc58128_devs[dev]);
    191    } else {
    192        abort();
    193    }
    194    return 1;
    195}
    196
    197static sh7750_io_device tc58128 = {
    198    RE | WE,			/* Port A triggers */
    199    0,				/* Port B triggers */
    200    tc58128_cb			/* Callback */
    201};
    202
    203int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
    204{
    205    init_dev(&tc58128_devs[0], zone1);
    206    init_dev(&tc58128_devs[1], zone2);
    207    return sh7750_register_io_device(s, &tc58128);
    208}