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

onenand.c (26454B)


      1/*
      2 * OneNAND flash memories emulation.
      3 *
      4 * Copyright (C) 2008 Nokia Corporation
      5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
      6 *
      7 * This program is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU General Public License as
      9 * published by the Free Software Foundation; either version 2 or
     10 * (at your option) version 3 of the License.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along
     18 * with this program; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "qapi/error.h"
     23#include "hw/hw.h"
     24#include "hw/block/flash.h"
     25#include "hw/irq.h"
     26#include "hw/qdev-properties.h"
     27#include "hw/qdev-properties-system.h"
     28#include "sysemu/block-backend.h"
     29#include "exec/memory.h"
     30#include "hw/sysbus.h"
     31#include "migration/vmstate.h"
     32#include "qemu/error-report.h"
     33#include "qemu/log.h"
     34#include "qemu/module.h"
     35#include "qom/object.h"
     36
     37/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
     38#define PAGE_SHIFT	11
     39
     40/* Fixed */
     41#define BLOCK_SHIFT	(PAGE_SHIFT + 6)
     42
     43#define TYPE_ONE_NAND "onenand"
     44OBJECT_DECLARE_SIMPLE_TYPE(OneNANDState, ONE_NAND)
     45
     46struct OneNANDState {
     47    SysBusDevice parent_obj;
     48
     49    struct {
     50        uint16_t man;
     51        uint16_t dev;
     52        uint16_t ver;
     53    } id;
     54    int shift;
     55    hwaddr base;
     56    qemu_irq intr;
     57    qemu_irq rdy;
     58    BlockBackend *blk;
     59    BlockBackend *blk_cur;
     60    uint8_t *image;
     61    uint8_t *otp;
     62    uint8_t *current;
     63    MemoryRegion ram;
     64    MemoryRegion mapped_ram;
     65    uint8_t current_direction;
     66    uint8_t *boot[2];
     67    uint8_t *data[2][2];
     68    MemoryRegion iomem;
     69    MemoryRegion container;
     70    int cycle;
     71    int otpmode;
     72
     73    uint16_t addr[8];
     74    uint16_t unladdr[8];
     75    int bufaddr;
     76    int count;
     77    uint16_t command;
     78    uint16_t config[2];
     79    uint16_t status;
     80    uint16_t intstatus;
     81    uint16_t wpstatus;
     82
     83    ECCState ecc;
     84
     85    int density_mask;
     86    int secs;
     87    int secs_cur;
     88    int blocks;
     89    uint8_t *blockwp;
     90};
     91
     92enum {
     93    ONEN_BUF_BLOCK = 0,
     94    ONEN_BUF_BLOCK2 = 1,
     95    ONEN_BUF_DEST_BLOCK = 2,
     96    ONEN_BUF_DEST_PAGE = 3,
     97    ONEN_BUF_PAGE = 7,
     98};
     99
    100enum {
    101    ONEN_ERR_CMD = 1 << 10,
    102    ONEN_ERR_ERASE = 1 << 11,
    103    ONEN_ERR_PROG = 1 << 12,
    104    ONEN_ERR_LOAD = 1 << 13,
    105};
    106
    107enum {
    108    ONEN_INT_RESET = 1 << 4,
    109    ONEN_INT_ERASE = 1 << 5,
    110    ONEN_INT_PROG = 1 << 6,
    111    ONEN_INT_LOAD = 1 << 7,
    112    ONEN_INT = 1 << 15,
    113};
    114
    115enum {
    116    ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
    117    ONEN_LOCK_LOCKED = 1 << 1,
    118    ONEN_LOCK_UNLOCKED = 1 << 2,
    119};
    120
    121static void onenand_mem_setup(OneNANDState *s)
    122{
    123    /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
    124     * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
    125     * write boot commands.  Also take note of the BWPS bit.  */
    126    memory_region_init(&s->container, OBJECT(s), "onenand",
    127                       0x10000 << s->shift);
    128    memory_region_add_subregion(&s->container, 0, &s->iomem);
    129    memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram",
    130                             &s->ram, 0x0200 << s->shift,
    131                             0xbe00 << s->shift);
    132    memory_region_add_subregion_overlap(&s->container,
    133                                        0x0200 << s->shift,
    134                                        &s->mapped_ram,
    135                                        1);
    136}
    137
    138static void onenand_intr_update(OneNANDState *s)
    139{
    140    qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
    141}
    142
    143static int onenand_pre_save(void *opaque)
    144{
    145    OneNANDState *s = opaque;
    146    if (s->current == s->otp) {
    147        s->current_direction = 1;
    148    } else if (s->current == s->image) {
    149        s->current_direction = 2;
    150    } else {
    151        s->current_direction = 0;
    152    }
    153
    154    return 0;
    155}
    156
    157static int onenand_post_load(void *opaque, int version_id)
    158{
    159    OneNANDState *s = opaque;
    160    switch (s->current_direction) {
    161    case 0:
    162        break;
    163    case 1:
    164        s->current = s->otp;
    165        break;
    166    case 2:
    167        s->current = s->image;
    168        break;
    169    default:
    170        return -1;
    171    }
    172    onenand_intr_update(s);
    173    return 0;
    174}
    175
    176static const VMStateDescription vmstate_onenand = {
    177    .name = "onenand",
    178    .version_id = 1,
    179    .minimum_version_id = 1,
    180    .pre_save = onenand_pre_save,
    181    .post_load = onenand_post_load,
    182    .fields = (VMStateField[]) {
    183        VMSTATE_UINT8(current_direction, OneNANDState),
    184        VMSTATE_INT32(cycle, OneNANDState),
    185        VMSTATE_INT32(otpmode, OneNANDState),
    186        VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
    187        VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
    188        VMSTATE_INT32(bufaddr, OneNANDState),
    189        VMSTATE_INT32(count, OneNANDState),
    190        VMSTATE_UINT16(command, OneNANDState),
    191        VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
    192        VMSTATE_UINT16(status, OneNANDState),
    193        VMSTATE_UINT16(intstatus, OneNANDState),
    194        VMSTATE_UINT16(wpstatus, OneNANDState),
    195        VMSTATE_INT32(secs_cur, OneNANDState),
    196        VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
    197        VMSTATE_UINT8(ecc.cp, OneNANDState),
    198        VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
    199        VMSTATE_UINT16(ecc.count, OneNANDState),
    200        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
    201            ((64 + 2) << PAGE_SHIFT)),
    202        VMSTATE_END_OF_LIST()
    203    }
    204};
    205
    206/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
    207static void onenand_reset(OneNANDState *s, int cold)
    208{
    209    memset(&s->addr, 0, sizeof(s->addr));
    210    s->command = 0;
    211    s->count = 1;
    212    s->bufaddr = 0;
    213    s->config[0] = 0x40c0;
    214    s->config[1] = 0x0000;
    215    onenand_intr_update(s);
    216    qemu_irq_raise(s->rdy);
    217    s->status = 0x0000;
    218    s->intstatus = cold ? 0x8080 : 0x8010;
    219    s->unladdr[0] = 0;
    220    s->unladdr[1] = 0;
    221    s->wpstatus = 0x0002;
    222    s->cycle = 0;
    223    s->otpmode = 0;
    224    s->blk_cur = s->blk;
    225    s->current = s->image;
    226    s->secs_cur = s->secs;
    227
    228    if (cold) {
    229        /* Lock the whole flash */
    230        memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
    231
    232        if (s->blk_cur && blk_pread(s->blk_cur, 0, s->boot[0],
    233                                    8 << BDRV_SECTOR_BITS) < 0) {
    234            hw_error("%s: Loading the BootRAM failed.\n", __func__);
    235        }
    236    }
    237}
    238
    239static void onenand_system_reset(DeviceState *dev)
    240{
    241    OneNANDState *s = ONE_NAND(dev);
    242
    243    onenand_reset(s, 1);
    244}
    245
    246static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
    247                void *dest)
    248{
    249    assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec);
    250    assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
    251    if (s->blk_cur) {
    252        return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS, dest,
    253                         secn << BDRV_SECTOR_BITS) < 0;
    254    } else if (sec + secn > s->secs_cur) {
    255        return 1;
    256    }
    257
    258    memcpy(dest, s->current + (sec << 9), secn << 9);
    259
    260    return 0;
    261}
    262
    263static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
    264                void *src)
    265{
    266    int result = 0;
    267
    268    if (secn > 0) {
    269        uint32_t size = secn << BDRV_SECTOR_BITS;
    270        uint32_t offset = sec << BDRV_SECTOR_BITS;
    271        assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec);
    272        assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
    273        const uint8_t *sp = (const uint8_t *)src;
    274        uint8_t *dp = 0;
    275        if (s->blk_cur) {
    276            dp = g_malloc(size);
    277            if (!dp || blk_pread(s->blk_cur, offset, dp, size) < 0) {
    278                result = 1;
    279            }
    280        } else {
    281            if (sec + secn > s->secs_cur) {
    282                result = 1;
    283            } else {
    284                dp = (uint8_t *)s->current + offset;
    285            }
    286        }
    287        if (!result) {
    288            uint32_t i;
    289            for (i = 0; i < size; i++) {
    290                dp[i] &= sp[i];
    291            }
    292            if (s->blk_cur) {
    293                result = blk_pwrite(s->blk_cur, offset, dp, size, 0) < 0;
    294            }
    295        }
    296        if (dp && s->blk_cur) {
    297            g_free(dp);
    298        }
    299    }
    300
    301    return result;
    302}
    303
    304static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
    305                void *dest)
    306{
    307    uint8_t buf[512];
    308
    309    if (s->blk_cur) {
    310        uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
    311        if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE) < 0) {
    312            return 1;
    313        }
    314        memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
    315    } else if (sec + secn > s->secs_cur) {
    316        return 1;
    317    } else {
    318        memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
    319    }
    320
    321    return 0;
    322}
    323
    324static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
    325                void *src)
    326{
    327    int result = 0;
    328    if (secn > 0) {
    329        const uint8_t *sp = (const uint8_t *)src;
    330        uint8_t *dp = 0, *dpp = 0;
    331        uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
    332        assert(UINT32_MAX >> BDRV_SECTOR_BITS > s->secs_cur + (sec >> 5));
    333        if (s->blk_cur) {
    334            dp = g_malloc(512);
    335            if (!dp
    336                || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE) < 0) {
    337                result = 1;
    338            } else {
    339                dpp = dp + ((sec & 31) << 4);
    340            }
    341        } else {
    342            if (sec + secn > s->secs_cur) {
    343                result = 1;
    344            } else {
    345                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
    346            }
    347        }
    348        if (!result) {
    349            uint32_t i;
    350            for (i = 0; i < (secn << 4); i++) {
    351                dpp[i] &= sp[i];
    352            }
    353            if (s->blk_cur) {
    354                result = blk_pwrite(s->blk_cur, offset, dp,
    355                                    BDRV_SECTOR_SIZE, 0) < 0;
    356            }
    357        }
    358        g_free(dp);
    359    }
    360    return result;
    361}
    362
    363static inline int onenand_erase(OneNANDState *s, int sec, int num)
    364{
    365    uint8_t *blankbuf, *tmpbuf;
    366
    367    blankbuf = g_malloc(512);
    368    tmpbuf = g_malloc(512);
    369    memset(blankbuf, 0xff, 512);
    370    for (; num > 0; num--, sec++) {
    371        if (s->blk_cur) {
    372            int erasesec = s->secs_cur + (sec >> 5);
    373            if (blk_pwrite(s->blk_cur, sec << BDRV_SECTOR_BITS, blankbuf,
    374                           BDRV_SECTOR_SIZE, 0) < 0) {
    375                goto fail;
    376            }
    377            if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
    378                          BDRV_SECTOR_SIZE) < 0) {
    379                goto fail;
    380            }
    381            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
    382            if (blk_pwrite(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
    383                           BDRV_SECTOR_SIZE, 0) < 0) {
    384                goto fail;
    385            }
    386        } else {
    387            if (sec + 1 > s->secs_cur) {
    388                goto fail;
    389            }
    390            memcpy(s->current + (sec << 9), blankbuf, 512);
    391            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
    392                   blankbuf, 1 << 4);
    393        }
    394    }
    395
    396    g_free(tmpbuf);
    397    g_free(blankbuf);
    398    return 0;
    399
    400fail:
    401    g_free(tmpbuf);
    402    g_free(blankbuf);
    403    return 1;
    404}
    405
    406static void onenand_command(OneNANDState *s)
    407{
    408    int b;
    409    int sec;
    410    void *buf;
    411#define SETADDR(block, page)			\
    412    sec = (s->addr[page] & 3) +			\
    413            ((((s->addr[page] >> 2) & 0x3f) +	\
    414              (((s->addr[block] & 0xfff) |	\
    415                (s->addr[block] >> 15 ?		\
    416                 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
    417#define SETBUF_M()				\
    418    buf = (s->bufaddr & 8) ?			\
    419            s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];	\
    420    buf += (s->bufaddr & 3) << 9;
    421#define SETBUF_S()				\
    422    buf = (s->bufaddr & 8) ?			\
    423            s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];	\
    424    buf += (s->bufaddr & 3) << 4;
    425
    426    switch (s->command) {
    427    case 0x00:	/* Load single/multiple sector data unit into buffer */
    428        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    429
    430        SETBUF_M()
    431        if (onenand_load_main(s, sec, s->count, buf))
    432            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
    433
    434#if 0
    435        SETBUF_S()
    436        if (onenand_load_spare(s, sec, s->count, buf))
    437            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
    438#endif
    439
    440        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
    441         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
    442         * then we need two split the read/write into two chunks.
    443         */
    444        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
    445        break;
    446    case 0x13:	/* Load single/multiple spare sector into buffer */
    447        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    448
    449        SETBUF_S()
    450        if (onenand_load_spare(s, sec, s->count, buf))
    451            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
    452
    453        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
    454         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
    455         * then we need two split the read/write into two chunks.
    456         */
    457        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
    458        break;
    459    case 0x80:	/* Program single/multiple sector data unit from buffer */
    460        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    461
    462        SETBUF_M()
    463        if (onenand_prog_main(s, sec, s->count, buf))
    464            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
    465
    466#if 0
    467        SETBUF_S()
    468        if (onenand_prog_spare(s, sec, s->count, buf))
    469            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
    470#endif
    471
    472        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
    473         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
    474         * then we need two split the read/write into two chunks.
    475         */
    476        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
    477        break;
    478    case 0x1a:	/* Program single/multiple spare area sector from buffer */
    479        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    480
    481        SETBUF_S()
    482        if (onenand_prog_spare(s, sec, s->count, buf))
    483            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
    484
    485        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
    486         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
    487         * then we need two split the read/write into two chunks.
    488         */
    489        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
    490        break;
    491    case 0x1b:	/* Copy-back program */
    492        SETBUF_S()
    493
    494        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    495        if (onenand_load_main(s, sec, s->count, buf))
    496            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
    497
    498        SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
    499        if (onenand_prog_main(s, sec, s->count, buf))
    500            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
    501
    502        /* TODO: spare areas */
    503
    504        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
    505        break;
    506
    507    case 0x23:	/* Unlock NAND array block(s) */
    508        s->intstatus |= ONEN_INT;
    509
    510        /* XXX the previous (?) area should be locked automatically */
    511        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
    512            if (b >= s->blocks) {
    513                s->status |= ONEN_ERR_CMD;
    514                break;
    515            }
    516            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
    517                break;
    518
    519            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
    520        }
    521        break;
    522    case 0x27:	/* Unlock All NAND array blocks */
    523        s->intstatus |= ONEN_INT;
    524
    525        for (b = 0; b < s->blocks; b ++) {
    526            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
    527                break;
    528
    529            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
    530        }
    531        break;
    532
    533    case 0x2a:	/* Lock NAND array block(s) */
    534        s->intstatus |= ONEN_INT;
    535
    536        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
    537            if (b >= s->blocks) {
    538                s->status |= ONEN_ERR_CMD;
    539                break;
    540            }
    541            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
    542                break;
    543
    544            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
    545        }
    546        break;
    547    case 0x2c:	/* Lock-tight NAND array block(s) */
    548        s->intstatus |= ONEN_INT;
    549
    550        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
    551            if (b >= s->blocks) {
    552                s->status |= ONEN_ERR_CMD;
    553                break;
    554            }
    555            if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
    556                continue;
    557
    558            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
    559        }
    560        break;
    561
    562    case 0x71:	/* Erase-Verify-Read */
    563        s->intstatus |= ONEN_INT;
    564        break;
    565    case 0x95:	/* Multi-block erase */
    566        qemu_irq_pulse(s->intr);
    567        /* Fall through.  */
    568    case 0x94:	/* Block erase */
    569        sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
    570                        (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
    571                << (BLOCK_SHIFT - 9);
    572        if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
    573            s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
    574
    575        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
    576        break;
    577    case 0xb0:	/* Erase suspend */
    578        break;
    579    case 0x30:	/* Erase resume */
    580        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
    581        break;
    582
    583    case 0xf0:	/* Reset NAND Flash core */
    584        onenand_reset(s, 0);
    585        break;
    586    case 0xf3:	/* Reset OneNAND */
    587        onenand_reset(s, 0);
    588        break;
    589
    590    case 0x65:	/* OTP Access */
    591        s->intstatus |= ONEN_INT;
    592        s->blk_cur = NULL;
    593        s->current = s->otp;
    594        s->secs_cur = 1 << (BLOCK_SHIFT - 9);
    595        s->addr[ONEN_BUF_BLOCK] = 0;
    596        s->otpmode = 1;
    597        break;
    598
    599    default:
    600        s->status |= ONEN_ERR_CMD;
    601        s->intstatus |= ONEN_INT;
    602        qemu_log_mask(LOG_GUEST_ERROR, "unknown OneNAND command %x\n",
    603                      s->command);
    604    }
    605
    606    onenand_intr_update(s);
    607}
    608
    609static uint64_t onenand_read(void *opaque, hwaddr addr,
    610                             unsigned size)
    611{
    612    OneNANDState *s = (OneNANDState *) opaque;
    613    int offset = addr >> s->shift;
    614
    615    switch (offset) {
    616    case 0x0000 ... 0xbffe:
    617        return lduw_le_p(s->boot[0] + addr);
    618
    619    case 0xf000:	/* Manufacturer ID */
    620        return s->id.man;
    621    case 0xf001:	/* Device ID */
    622        return s->id.dev;
    623    case 0xf002:	/* Version ID */
    624        return s->id.ver;
    625    /* TODO: get the following values from a real chip!  */
    626    case 0xf003:	/* Data Buffer size */
    627        return 1 << PAGE_SHIFT;
    628    case 0xf004:	/* Boot Buffer size */
    629        return 0x200;
    630    case 0xf005:	/* Amount of buffers */
    631        return 1 | (2 << 8);
    632    case 0xf006:	/* Technology */
    633        return 0;
    634
    635    case 0xf100 ... 0xf107:	/* Start addresses */
    636        return s->addr[offset - 0xf100];
    637
    638    case 0xf200:	/* Start buffer */
    639        return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
    640
    641    case 0xf220:	/* Command */
    642        return s->command;
    643    case 0xf221:	/* System Configuration 1 */
    644        return s->config[0] & 0xffe0;
    645    case 0xf222:	/* System Configuration 2 */
    646        return s->config[1];
    647
    648    case 0xf240:	/* Controller Status */
    649        return s->status;
    650    case 0xf241:	/* Interrupt */
    651        return s->intstatus;
    652    case 0xf24c:	/* Unlock Start Block Address */
    653        return s->unladdr[0];
    654    case 0xf24d:	/* Unlock End Block Address */
    655        return s->unladdr[1];
    656    case 0xf24e:	/* Write Protection Status */
    657        return s->wpstatus;
    658
    659    case 0xff00:	/* ECC Status */
    660        return 0x00;
    661    case 0xff01:	/* ECC Result of main area data */
    662    case 0xff02:	/* ECC Result of spare area data */
    663    case 0xff03:	/* ECC Result of main area data */
    664    case 0xff04:	/* ECC Result of spare area data */
    665        qemu_log_mask(LOG_UNIMP,
    666                      "onenand: ECC result registers unimplemented\n");
    667        return 0x0000;
    668    }
    669
    670    qemu_log_mask(LOG_GUEST_ERROR, "read of unknown OneNAND register 0x%x\n",
    671                  offset);
    672    return 0;
    673}
    674
    675static void onenand_write(void *opaque, hwaddr addr,
    676                          uint64_t value, unsigned size)
    677{
    678    OneNANDState *s = (OneNANDState *) opaque;
    679    int offset = addr >> s->shift;
    680    int sec;
    681
    682    switch (offset) {
    683    case 0x0000 ... 0x01ff:
    684    case 0x8000 ... 0x800f:
    685        if (s->cycle) {
    686            s->cycle = 0;
    687
    688            if (value == 0x0000) {
    689                SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
    690                onenand_load_main(s, sec,
    691                                1 << (PAGE_SHIFT - 9), s->data[0][0]);
    692                s->addr[ONEN_BUF_PAGE] += 4;
    693                s->addr[ONEN_BUF_PAGE] &= 0xff;
    694            }
    695            break;
    696        }
    697
    698        switch (value) {
    699        case 0x00f0:	/* Reset OneNAND */
    700            onenand_reset(s, 0);
    701            break;
    702
    703        case 0x00e0:	/* Load Data into Buffer */
    704            s->cycle = 1;
    705            break;
    706
    707        case 0x0090:	/* Read Identification Data */
    708            memset(s->boot[0], 0, 3 << s->shift);
    709            s->boot[0][0 << s->shift] = s->id.man & 0xff;
    710            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
    711            s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
    712            break;
    713
    714        default:
    715            qemu_log_mask(LOG_GUEST_ERROR,
    716                          "unknown OneNAND boot command %" PRIx64 "\n",
    717                          value);
    718        }
    719        break;
    720
    721    case 0xf100 ... 0xf107:	/* Start addresses */
    722        s->addr[offset - 0xf100] = value;
    723        break;
    724
    725    case 0xf200:	/* Start buffer */
    726        s->bufaddr = (value >> 8) & 0xf;
    727        if (PAGE_SHIFT == 11)
    728            s->count = (value & 3) ?: 4;
    729        else if (PAGE_SHIFT == 10)
    730            s->count = (value & 1) ?: 2;
    731        break;
    732
    733    case 0xf220:	/* Command */
    734        if (s->intstatus & (1 << 15))
    735            break;
    736        s->command = value;
    737        onenand_command(s);
    738        break;
    739    case 0xf221:	/* System Configuration 1 */
    740        s->config[0] = value;
    741        onenand_intr_update(s);
    742        qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
    743        break;
    744    case 0xf222:	/* System Configuration 2 */
    745        s->config[1] = value;
    746        break;
    747
    748    case 0xf241:	/* Interrupt */
    749        s->intstatus &= value;
    750        if ((1 << 15) & ~s->intstatus)
    751            s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
    752                            ONEN_ERR_PROG | ONEN_ERR_LOAD);
    753        onenand_intr_update(s);
    754        break;
    755    case 0xf24c:	/* Unlock Start Block Address */
    756        s->unladdr[0] = value & (s->blocks - 1);
    757        /* For some reason we have to set the end address to by default
    758         * be same as start because the software forgets to write anything
    759         * in there.  */
    760        s->unladdr[1] = value & (s->blocks - 1);
    761        break;
    762    case 0xf24d:	/* Unlock End Block Address */
    763        s->unladdr[1] = value & (s->blocks - 1);
    764        break;
    765
    766    default:
    767        qemu_log_mask(LOG_GUEST_ERROR,
    768                      "write to unknown OneNAND register 0x%x\n",
    769                      offset);
    770    }
    771}
    772
    773static const MemoryRegionOps onenand_ops = {
    774    .read = onenand_read,
    775    .write = onenand_write,
    776    .endianness = DEVICE_NATIVE_ENDIAN,
    777};
    778
    779static void onenand_realize(DeviceState *dev, Error **errp)
    780{
    781    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    782    OneNANDState *s = ONE_NAND(dev);
    783    uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
    784    void *ram;
    785    Error *local_err = NULL;
    786
    787    s->base = (hwaddr)-1;
    788    s->rdy = NULL;
    789    s->blocks = size >> BLOCK_SHIFT;
    790    s->secs = size >> 9;
    791    s->blockwp = g_malloc(s->blocks);
    792    s->density_mask = (s->id.dev & 0x08)
    793        ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
    794    memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
    795                          0x10000 << s->shift);
    796    if (!s->blk) {
    797        s->image = memset(g_malloc(size + (size >> 5)),
    798                          0xff, size + (size >> 5));
    799    } else {
    800        if (!blk_supports_write_perm(s->blk)) {
    801            error_setg(errp, "Can't use a read-only drive");
    802            return;
    803        }
    804        blk_set_perm(s->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
    805                     BLK_PERM_ALL, &local_err);
    806        if (local_err) {
    807            error_propagate(errp, local_err);
    808            return;
    809        }
    810        s->blk_cur = s->blk;
    811    }
    812    s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
    813                    0xff, (64 + 2) << PAGE_SHIFT);
    814    memory_region_init_ram_nomigrate(&s->ram, OBJECT(s), "onenand.ram",
    815                           0xc000 << s->shift, &error_fatal);
    816    vmstate_register_ram_global(&s->ram);
    817    ram = memory_region_get_ram_ptr(&s->ram);
    818    s->boot[0] = ram + (0x0000 << s->shift);
    819    s->boot[1] = ram + (0x8000 << s->shift);
    820    s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
    821    s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
    822    s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
    823    s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
    824    onenand_mem_setup(s);
    825    sysbus_init_irq(sbd, &s->intr);
    826    sysbus_init_mmio(sbd, &s->container);
    827    vmstate_register(VMSTATE_IF(dev),
    828                     ((s->shift & 0x7f) << 24)
    829                     | ((s->id.man & 0xff) << 16)
    830                     | ((s->id.dev & 0xff) << 8)
    831                     | (s->id.ver & 0xff),
    832                     &vmstate_onenand, s);
    833}
    834
    835static Property onenand_properties[] = {
    836    DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
    837    DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
    838    DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
    839    DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
    840    DEFINE_PROP_DRIVE("drive", OneNANDState, blk),
    841    DEFINE_PROP_END_OF_LIST(),
    842};
    843
    844static void onenand_class_init(ObjectClass *klass, void *data)
    845{
    846    DeviceClass *dc = DEVICE_CLASS(klass);
    847
    848    dc->realize = onenand_realize;
    849    dc->reset = onenand_system_reset;
    850    device_class_set_props(dc, onenand_properties);
    851}
    852
    853static const TypeInfo onenand_info = {
    854    .name          = TYPE_ONE_NAND,
    855    .parent        = TYPE_SYS_BUS_DEVICE,
    856    .instance_size = sizeof(OneNANDState),
    857    .class_init    = onenand_class_init,
    858};
    859
    860static void onenand_register_types(void)
    861{
    862    type_register_static(&onenand_info);
    863}
    864
    865void *onenand_raw_otp(DeviceState *onenand_device)
    866{
    867    OneNANDState *s = ONE_NAND(onenand_device);
    868
    869    return s->otp;
    870}
    871
    872type_init(onenand_register_types)