pflash_cfi01: add secure property
When this property is set, MMIO accesses are only allowed with the MEMTXATTRS_SECURE attribute. This is used for secure access to UEFI variables stored in flash. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									5aa113f0a2
								
							
						
					
					
						commit
						f71e42a5c9
					
				| 
						 | 
				
			
			@ -65,6 +65,7 @@ do {                                                        \
 | 
			
		|||
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
 | 
			
		||||
 | 
			
		||||
#define PFLASH_BE          0
 | 
			
		||||
#define PFLASH_SECURE      1
 | 
			
		||||
 | 
			
		||||
struct pflash_t {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
| 
						 | 
				
			
			@ -237,12 +238,57 @@ static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
 | 
			
		|||
    return resp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
 | 
			
		||||
                                 int width, int be)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *p;
 | 
			
		||||
    uint32_t ret;
 | 
			
		||||
 | 
			
		||||
    p = pfl->storage;
 | 
			
		||||
    switch (width) {
 | 
			
		||||
    case 1:
 | 
			
		||||
        ret = p[offset];
 | 
			
		||||
        DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
 | 
			
		||||
                __func__, offset, ret);
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        if (be) {
 | 
			
		||||
            ret = p[offset] << 8;
 | 
			
		||||
            ret |= p[offset + 1];
 | 
			
		||||
        } else {
 | 
			
		||||
            ret = p[offset];
 | 
			
		||||
            ret |= p[offset + 1] << 8;
 | 
			
		||||
        }
 | 
			
		||||
        DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
 | 
			
		||||
                __func__, offset, ret);
 | 
			
		||||
        break;
 | 
			
		||||
    case 4:
 | 
			
		||||
        if (be) {
 | 
			
		||||
            ret = p[offset] << 24;
 | 
			
		||||
            ret |= p[offset + 1] << 16;
 | 
			
		||||
            ret |= p[offset + 2] << 8;
 | 
			
		||||
            ret |= p[offset + 3];
 | 
			
		||||
        } else {
 | 
			
		||||
            ret = p[offset];
 | 
			
		||||
            ret |= p[offset + 1] << 8;
 | 
			
		||||
            ret |= p[offset + 2] << 16;
 | 
			
		||||
            ret |= p[offset + 3] << 24;
 | 
			
		||||
        }
 | 
			
		||||
        DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
 | 
			
		||||
                __func__, offset, ret);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        DPRINTF("BUG in %s\n", __func__);
 | 
			
		||||
        abort();
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
 | 
			
		||||
                             int width, int be)
 | 
			
		||||
{
 | 
			
		||||
    hwaddr boff;
 | 
			
		||||
    uint32_t ret;
 | 
			
		||||
    uint8_t *p;
 | 
			
		||||
 | 
			
		||||
    ret = -1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -259,43 +305,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
 | 
			
		|||
        /* fall through to read code */
 | 
			
		||||
    case 0x00:
 | 
			
		||||
        /* Flash area read */
 | 
			
		||||
        p = pfl->storage;
 | 
			
		||||
        switch (width) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            ret = p[offset];
 | 
			
		||||
            DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
 | 
			
		||||
                    __func__, offset, ret);
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            if (be) {
 | 
			
		||||
                ret = p[offset] << 8;
 | 
			
		||||
                ret |= p[offset + 1];
 | 
			
		||||
            } else {
 | 
			
		||||
                ret = p[offset];
 | 
			
		||||
                ret |= p[offset + 1] << 8;
 | 
			
		||||
            }
 | 
			
		||||
            DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
 | 
			
		||||
                    __func__, offset, ret);
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            if (be) {
 | 
			
		||||
                ret = p[offset] << 24;
 | 
			
		||||
                ret |= p[offset + 1] << 16;
 | 
			
		||||
                ret |= p[offset + 2] << 8;
 | 
			
		||||
                ret |= p[offset + 3];
 | 
			
		||||
            } else {
 | 
			
		||||
                ret = p[offset];
 | 
			
		||||
                ret |= p[offset + 1] << 8;
 | 
			
		||||
                ret |= p[offset + 2] << 16;
 | 
			
		||||
                ret |= p[offset + 3] << 24;
 | 
			
		||||
            }
 | 
			
		||||
            DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
 | 
			
		||||
                    __func__, offset, ret);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            DPRINTF("BUG in %s\n", __func__);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = pflash_data_read(pfl, offset, width, be);
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x10: /* Single byte program */
 | 
			
		||||
    case 0x20: /* Block erase */
 | 
			
		||||
| 
						 | 
				
			
			@ -650,25 +660,37 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint64_t pflash_mem_read(void *opaque, hwaddr addr, unsigned len)
 | 
			
		||||
static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
 | 
			
		||||
                                              unsigned len, MemTxAttrs attrs)
 | 
			
		||||
{
 | 
			
		||||
    pflash_t *pfl = opaque;
 | 
			
		||||
    bool be = !!(pfl->features & (1 << PFLASH_BE));
 | 
			
		||||
 | 
			
		||||
    return pflash_read(pfl, addr, len, be);
 | 
			
		||||
    if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
 | 
			
		||||
        *value = pflash_data_read(opaque, addr, len, be);
 | 
			
		||||
    } else {
 | 
			
		||||
        *value = pflash_read(opaque, addr, len, be);
 | 
			
		||||
    }
 | 
			
		||||
    return MEMTX_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pflash_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned len)
 | 
			
		||||
static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
 | 
			
		||||
                                               unsigned len, MemTxAttrs attrs)
 | 
			
		||||
{
 | 
			
		||||
    pflash_t *pfl = opaque;
 | 
			
		||||
    bool be = !!(pfl->features & (1 << PFLASH_BE));
 | 
			
		||||
 | 
			
		||||
    pflash_write(pfl, addr, value, len, be);
 | 
			
		||||
    if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
 | 
			
		||||
        return MEMTX_ERROR;
 | 
			
		||||
    } else {
 | 
			
		||||
        pflash_write(opaque, addr, value, len, be);
 | 
			
		||||
        return MEMTX_OK;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const MemoryRegionOps pflash_cfi01_ops = {
 | 
			
		||||
    .read = pflash_mem_read,
 | 
			
		||||
    .write = pflash_mem_write,
 | 
			
		||||
    .read_with_attrs = pflash_mem_read_with_attrs,
 | 
			
		||||
    .write_with_attrs = pflash_mem_write_with_attrs,
 | 
			
		||||
    .endianness = DEVICE_NATIVE_ENDIAN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -853,6 +875,7 @@ static Property pflash_cfi01_properties[] = {
 | 
			
		|||
    DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
 | 
			
		||||
    DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
 | 
			
		||||
    DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
 | 
			
		||||
    DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
 | 
			
		||||
    DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
 | 
			
		||||
    DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
 | 
			
		||||
    DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue