qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC] Writeable files in fw_cfg


From: Blue Swirl
Subject: Re: [Qemu-devel] [RFC] Writeable files in fw_cfg
Date: Sun, 27 Jan 2013 15:14:34 +0000

On Sat, Jan 26, 2013 at 8:43 PM, David Woodhouse <address@hidden> wrote:
> For OVMF we really want to have a way to store non-volatile variables,
> other than the dirty hack that currently puts them on a file in the EFI
> system partition.
>
> It looks like we've supported writing to fw_cfg items fairly much since
> they were introduced, but we've never actually made use of that.
>
> This WIP patch kills the existing fw_cfg_add_callback() because I can't
> see how it would ever be useful, and it doesn't seem to have been used
> for years, if ever. And adds something slightly more useful.
>
> Other then the obvious bits that need finishing, any objections?

It looks like this duplicates rom_add_file() and fw_cfg_add_file(), so
I don't see the point.

Removing unused fw_cfg_add_callback() should be a separate patch and
that would be OK.

In general, QEMU uses different coding style from kernel, so please
read our CODING_STYLE and use checkpatch.pl to catch obvious problems,
like missing braces and C99 comments.

>
> diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
> index 3b31d77..1318a2e 100644
> --- a/hw/fw_cfg.c
> +++ b/hw/fw_cfg.c
> @@ -33,6 +33,9 @@
>  #define FW_CFG_SIZE 2
>  #define FW_CFG_DATA_SIZE 1
>
> +struct FWCfgEntry;
> +typedef void (*FWCfgCallback)(struct FWCfgState *s, struct FWCfgEntry *e, 
> int value);
> +
>  typedef struct FWCfgEntry {
>      uint32_t len;
>      uint8_t *data;
> @@ -206,20 +209,19 @@ static void fw_cfg_write(FWCfgState *s, uint8_t value)
>
>      trace_fw_cfg_write(s, value);
>
> -    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);
> -            s->cur_offset = 0;
> -        }
> -    }
> +    if (s->cur_entry & FW_CFG_WRITE_CHANNEL && e->callback)
> +        e->callback(s, e, value);
>  }
>
>  static int fw_cfg_select(FWCfgState *s, uint16_t key)
>  {
> +    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
> +    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
>      int ret;
>
> +    if (e->callback)
> +        e->callback(s, e, -1);
> +
>      s->cur_offset = 0;
>      if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) {
>          s->cur_entry = FW_CFG_INVALID;
> @@ -419,8 +421,8 @@ void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t 
> value)
>      fw_cfg_add_bytes(s, key, copy, sizeof(value));
>  }
>
> -void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
> -                         void *callback_opaque, void *data, size_t len)
> +static void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback 
> callback,
> +                                void *callback_opaque, void *data, size_t 
> len)
>  {
>      int arch = !!(key & FW_CFG_ARCH_LOCAL);
>
> @@ -436,8 +438,9 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, 
> FWCfgCallback callback,
>      s->entries[arch][key].callback = callback;
>  }
>
> -void fw_cfg_add_file(FWCfgState *s,  const char *filename,
> -                     void *data, size_t len)
> +static void fw_cfg_add_file_writeable(FWCfgState *s,  const char *filename,
> +                                      void *data, size_t len,
> +                                     FWCfgCallback callback, void *cb_opaque)
>  {
>      int i, index;
>      size_t dsize;
> @@ -451,7 +454,8 @@ void fw_cfg_add_file(FWCfgState *s,  const char *filename,
>      index = be32_to_cpu(s->files->count);
>      assert(index < FW_CFG_FILE_SLOTS);
>
> -    fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
> +    fw_cfg_add_callback(s, FW_CFG_WRITE_CHANNEL + FW_CFG_FILE_FIRST + index,
> +                        callback, cb_opaque, data, len);
>
>      pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
>              filename);
> @@ -464,11 +468,74 @@ void fw_cfg_add_file(FWCfgState *s,  const char 
> *filename,
>
>      s->files->f[index].size   = cpu_to_be32(len);
>      s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
> +    if (callback)
> +           s->files->f[index].select |= cpu_to_be16(FW_CFG_WRITE_CHANNEL);
>      trace_fw_cfg_add_file(s, index, s->files->f[index].name, len);
>
>      s->files->count = cpu_to_be32(index+1);
>  }
>
> +void fw_cfg_add_file(FWCfgState *s,  const char *filename,
> +                     void *data, size_t len)
> +{
> +    fw_cfg_add_file_writeable(s, filename, data, len, NULL, NULL);
> +}
> +
> +// Lifted from pc.c
> +static long get_file_size(FILE *f)
> +{
> +    long where, size;
> +
> +    /* XXX: on Unix systems, using fstat() probably makes more sense */
> +
> +    where = ftell(f);
> +    fseek(f, 0, SEEK_END);
> +    size = ftell(f);
> +    fseek(f, where, SEEK_SET);
> +
> +    return size;
> +}
> +
> +static void nvstorage_callback(struct FWCfgState *s, struct FWCfgEntry *e, 
> int value)
> +
> +{
> +    if (value == -1) {
> +        FILE *f = fopen(e->callback_opaque, "wb");
> +        if (f) {
> +            fwrite(e->data, e->len, 1, f);
> +            fclose(f);
> +        }
> +       return;
> +    }
> +    if (s->cur_offset == e->len)
> +        e->data = realloc(e->data, ++e->len);
> +    e->data[s->cur_offset++] = value;
> +}
> +
> +void fw_cfg_add_nvstorage(FWCfgState *s, const char *filename)
> +{
> +    FILE *f;
> +    int file_size = 0;
> +    int f2;
> +    uint8_t *data = NULL;
> +
> +    f = fopen(filename, "rb");
> +    if (f) {
> +        file_size = get_file_size(f);
> +       if (file_size) {
> +            data = malloc(file_size);
> +            if ((f2=fread(data, 1, file_size, f)) != file_size) {
> +                fprintf(stderr, "qemu: Could not load non-volatile storage 
> file '%s' %d %d: %s\n",
> +                        filename, file_size, f2, strerror(errno));
> +                exit(1);
> +            }
> +        }
> +        fclose(f);
> +    }
> +    fw_cfg_add_file_writeable(s, "etc/nvstorage", data, file_size,
> +                              nvstorage_callback, strdup(filename));
> +}
> +
>  static void fw_cfg_machine_ready(struct Notifier *n, void *data)
>  {
>      size_t len;
> @@ -507,6 +574,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t 
> data_port,
>      fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
>      fw_cfg_bootsplash(s);
>      fw_cfg_reboot(s);
> +    fw_cfg_add_nvstorage(s, "/tmp/nvstorage");
>
>      s->machine_ready.notify = fw_cfg_machine_ready;
>      qemu_add_machine_init_done_notifier(&s->machine_ready);
> diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
> index 05c8df1..298bc47 100644
> --- a/hw/fw_cfg.h
> +++ b/hw/fw_cfg.h
> @@ -51,20 +51,17 @@ typedef struct FWCfgFiles {
>      FWCfgFile f[];
>  } FWCfgFiles;
>
> -typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
> -
>  typedef struct FWCfgState FWCfgState;
>  void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
>  void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
>  void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
>  void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
>  void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
> -void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
> -                         void *callback_opaque, void *data, size_t len);
>  void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
>                       size_t len);
>  FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
>                          hwaddr crl_addr, hwaddr data_addr);
> +void fw_cfg_add_nvstorage(FWCfgState *s, const char *filename);
>
>  #endif /* NO_QEMU_PROTOS */
>
>
> --
> dwmw2
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]