#endif
#define FW_CFG_SIZE 2
+#define FW_CFG_DATA_SIZE 1
typedef struct FWCfgEntry {
uint32_t len;
struct FWCfgState {
SysBusDevice busdev;
+ MemoryRegion ctl_iomem, data_iomem, comb_iomem;
uint32_t ctl_iobase, data_iobase;
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
FWCfgFiles *files;
#define JPG_FILE 0
#define BMP_FILE 1
-static FILE *probe_splashfile(char *filename, int *file_sizep, int *file_typep)
+static char *read_splashfile(char *filename, int *file_sizep, int *file_typep)
{
- FILE *fp = NULL;
- int fop_ret;
- int file_size;
+ GError *err = NULL;
+ gboolean res;
+ gchar *content;
int file_type = -1;
- unsigned char buf[2] = {0, 0};
- unsigned int filehead_value = 0;
+ unsigned int filehead = 0;
int bmp_bpp;
- fp = fopen(filename, "rb");
- if (fp == NULL) {
- error_report("failed to open file '%s'.", filename);
- return fp;
+ res = g_file_get_contents(filename, &content, (gsize *)file_sizep, &err);
+ if (res == FALSE) {
+ error_report("failed to read splash file '%s'", filename);
+ g_error_free(err);
+ return NULL;
}
+
/* check file size */
- fseek(fp, 0L, SEEK_END);
- file_size = ftell(fp);
- if (file_size < 2) {
- error_report("file size is less than 2 bytes '%s'.", filename);
- fclose(fp);
- fp = NULL;
- return fp;
+ if (*file_sizep < 30) {
+ goto error;
}
+
/* check magic ID */
- fseek(fp, 0L, SEEK_SET);
- fop_ret = fread(buf, 1, 2, fp);
- if (fop_ret != 2) {
- error_report("Could not read header from '%s': %s",
- filename, strerror(errno));
- fclose(fp);
- fp = NULL;
- return fp;
- }
- filehead_value = (buf[0] + (buf[1] << 8)) & 0xffff;
- if (filehead_value == 0xd8ff) {
+ filehead = ((content[0] & 0xff) + (content[1] << 8)) & 0xffff;
+ if (filehead == 0xd8ff) {
file_type = JPG_FILE;
+ } else if (filehead == 0x4d42) {
+ file_type = BMP_FILE;
} else {
- if (filehead_value == 0x4d42) {
- file_type = BMP_FILE;
- }
- }
- if (file_type < 0) {
- error_report("'%s' not jpg/bmp file,head:0x%x.",
- filename, filehead_value);
- fclose(fp);
- fp = NULL;
- return fp;
+ goto error;
}
+
/* check BMP bpp */
if (file_type == BMP_FILE) {
- fseek(fp, 28, SEEK_SET);
- fop_ret = fread(buf, 1, 2, fp);
- bmp_bpp = (buf[0] + (buf[1] << 8)) & 0xffff;
+ bmp_bpp = (content[28] + (content[29] << 8)) & 0xffff;
if (bmp_bpp != 24) {
- error_report("only 24bpp bmp file is supported.");
- fclose(fp);
- fp = NULL;
- return fp;
+ goto error;
}
}
+
/* return values */
- *file_sizep = file_size;
*file_typep = file_type;
- return fp;
+
+ return content;
+
+error:
+ error_report("splash file '%s' format not recognized; must be JPEG "
+ "or 24 bit BMP", filename);
+ g_free(content);
+ return NULL;
}
static void fw_cfg_bootsplash(FWCfgState *s)
int boot_splash_time = -1;
const char *boot_splash_filename = NULL;
char *p;
- char *filename;
- FILE *fp;
- int fop_ret;
+ char *filename, *file_data;
int file_size;
int file_type = -1;
const char *temp;
error_report("failed to find file '%s'.", boot_splash_filename);
return;
}
- /* probing the file */
- fp = probe_splashfile(filename, &file_size, &file_type);
- if (fp == NULL) {
+
+ /* loading file data */
+ file_data = read_splashfile(filename, &file_size, &file_type);
+ if (file_data == NULL) {
g_free(filename);
return;
}
- /* loading file data */
if (boot_splash_filedata != NULL) {
g_free(boot_splash_filedata);
}
- boot_splash_filedata = g_malloc(file_size);
+ boot_splash_filedata = (uint8_t *)file_data;
boot_splash_filedata_size = file_size;
- fseek(fp, 0L, SEEK_SET);
- fop_ret = fread(boot_splash_filedata, 1, file_size, fp);
- if (fop_ret != file_size) {
- error_report("failed to read data from '%s'.",
- boot_splash_filename);
- fclose(fp);
- return;
- }
- fclose(fp);
+
/* insert data */
if (file_type == JPG_FILE) {
fw_cfg_add_file(s, "bootsplash.jpg",
FW_CFG_DPRINTF("write %d\n", value);
- if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) {
+ if (s->cur_entry & FW_CFG_WRITE_CHANNEL && e->callback &&
+ s->cur_offset < e->len) {
e->data[s->cur_offset++] = value;
if (s->cur_offset == e->len) {
e->callback(e->callback_opaque, e->data);
return ret;
}
-static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
+static uint64_t fw_cfg_data_mem_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
return fw_cfg_read(opaque);
}
-static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_data_mem_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
{
fw_cfg_write(opaque, (uint8_t)value);
}
-static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
+static void fw_cfg_ctl_mem_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
{
fw_cfg_select(opaque, (uint16_t)value);
}
-static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
+static bool fw_cfg_ctl_mem_valid(void *opaque, target_phys_addr_t addr,
+ unsigned size, bool is_write)
{
- return fw_cfg_read(opaque);
+ return is_write && size == 2;
}
-static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t value)
+static uint64_t fw_cfg_comb_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
- fw_cfg_write(opaque, (uint8_t)value);
+ return fw_cfg_read(opaque);
}
-static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
- uint32_t value)
+static void fw_cfg_comb_write(void *opaque, target_phys_addr_t addr,
+ uint64_t value, unsigned size)
{
- fw_cfg_select(opaque, (uint16_t)value);
+ switch (size) {
+ case 1:
+ fw_cfg_write(opaque, (uint8_t)value);
+ break;
+ case 2:
+ fw_cfg_select(opaque, (uint16_t)value);
+ break;
+ }
}
-static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
- NULL,
- NULL,
- NULL,
-};
+static bool fw_cfg_comb_valid(void *opaque, target_phys_addr_t addr,
+ unsigned size, bool is_write)
+{
+ return (size == 1) || (is_write && size == 2);
+}
-static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
- NULL,
- fw_cfg_mem_writew,
- NULL,
+static const MemoryRegionOps fw_cfg_ctl_mem_ops = {
+ .write = fw_cfg_ctl_mem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.accepts = fw_cfg_ctl_mem_valid,
};
-static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
- fw_cfg_mem_readb,
- NULL,
- NULL,
+static const MemoryRegionOps fw_cfg_data_mem_ops = {
+ .read = fw_cfg_data_mem_read,
+ .write = fw_cfg_data_mem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
};
-static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
- fw_cfg_mem_writeb,
- NULL,
- NULL,
+static const MemoryRegionOps fw_cfg_comb_mem_ops = {
+ .read = fw_cfg_comb_read,
+ .write = fw_cfg_comb_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.accepts = fw_cfg_comb_valid,
};
static void fw_cfg_reset(DeviceState *d)
static int fw_cfg_init1(SysBusDevice *dev)
{
FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
- int io_ctl_memory, io_data_memory;
-
- io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
- fw_cfg_ctl_mem_write, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
- io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
- fw_cfg_data_mem_write, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
-
- if (s->ctl_iobase) {
- register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
- }
- if (s->data_iobase) {
- register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
- register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
+ memory_region_init_io(&s->ctl_iomem, &fw_cfg_ctl_mem_ops, s,
+ "fwcfg.ctl", FW_CFG_SIZE);
+ sysbus_init_mmio(dev, &s->ctl_iomem);
+ memory_region_init_io(&s->data_iomem, &fw_cfg_data_mem_ops, s,
+ "fwcfg.data", FW_CFG_DATA_SIZE);
+ sysbus_init_mmio(dev, &s->data_iomem);
+ /* In case ctl and data overlap: */
+ memory_region_init_io(&s->comb_iomem, &fw_cfg_comb_mem_ops, s,
+ "fwcfg", FW_CFG_SIZE);
+
+ if (s->ctl_iobase + 1 == s->data_iobase) {
+ sysbus_add_io(dev, s->ctl_iobase, &s->comb_iomem);
+ } else {
+ if (s->ctl_iobase) {
+ sysbus_add_io(dev, s->ctl_iobase, &s->ctl_iomem);
+ }
+ if (s->data_iobase) {
+ sysbus_add_io(dev, s->data_iobase, &s->data_iomem);
+ }
}
return 0;
}
-static SysBusDeviceInfo fw_cfg_info = {
- .init = fw_cfg_init1,
- .qdev.name = "fw_cfg",
- .qdev.size = sizeof(FWCfgState),
- .qdev.vmsd = &vmstate_fw_cfg,
- .qdev.reset = fw_cfg_reset,
- .qdev.no_user = 1,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
- DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
- DEFINE_PROP_END_OF_LIST(),
- },
+static Property fw_cfg_properties[] = {
+ DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
+ DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void fw_cfg_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = fw_cfg_init1;
+ dc->no_user = 1;
+ dc->reset = fw_cfg_reset;
+ dc->vmsd = &vmstate_fw_cfg;
+ dc->props = fw_cfg_properties;
+}
+
+static TypeInfo fw_cfg_info = {
+ .name = "fw_cfg",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FWCfgState),
+ .class_init = fw_cfg_class_init,
};
-static void fw_cfg_register_devices(void)
+static void fw_cfg_register_types(void)
{
- sysbus_register_withprop(&fw_cfg_info);
+ type_register_static(&fw_cfg_info);
}
-device_init(fw_cfg_register_devices)
+type_init(fw_cfg_register_types)