rfs: Consistent coding style, cleanup and fresh new implementation
authorPaul Kocialkowski <contact@paulk.fr>
Sat, 15 Feb 2014 11:03:32 +0000 (12:03 +0100)
committerPaul Kocialkowski <contact@paulk.fr>
Sat, 15 Feb 2014 11:03:32 +0000 (12:03 +0100)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
include/rfs.h
samsung-ipc/devices/xmm6160/xmm6160.c
samsung-ipc/devices/xmm6260/xmm6260_hsic.c
samsung-ipc/devices/xmm6260/xmm6260_mipi.c
samsung-ipc/rfs.c

index d56f05a..acfd018 100644 (file)
  * Structures
  */
 
-struct ipc_rfs_nv_read_item_data {
+struct ipc_rfs_nv_read_item_request_data {
     unsigned int offset;
     unsigned int length;
 } __attribute__((__packed__));
 
-struct ipc_rfs_nv_read_item_confirm_header {
+struct ipc_rfs_nv_read_item_response_header {
     unsigned char confirm;
     unsigned int offset;
     unsigned int length;
 } __attribute__((__packed__));
 
-struct ipc_rfs_nv_write_item_header {
+struct ipc_rfs_nv_write_item_request_header {
     unsigned int offset;
     unsigned int length;
 } __attribute__((__packed__));
 
-struct ipc_rfs_nv_write_item_confirm_data {
+struct ipc_rfs_nv_write_item_response_data {
     unsigned char confirm;
     unsigned int offset;
     unsigned int length;
@@ -59,21 +59,22 @@ struct ipc_rfs_nv_write_item_confirm_data {
  * Helpers
  */
 
-void md5hash2string(char *out, unsigned char *in);
-void nv_data_generate(struct ipc_client *client);
-void nv_data_md5_compute(void *data_p, int size, char *secret, void *hash);
-void nv_data_md5_generate(struct ipc_client *client);
-void nv_data_backup_create(struct ipc_client *client);
-void nv_data_backup_restore(struct ipc_client *client);
-int nv_data_check(struct ipc_client *client);
-int nv_data_md5_check(struct ipc_client *client);
-int nv_data_read(struct ipc_client *client, int offset, int length, char *buf);
-int nv_data_write(struct ipc_client *client, int offset, int length, char *buf);
-
-void ipc_rfs_send_io_confirm_for_nv_write_item(struct ipc_client *client,
-    struct ipc_message_info *info);
-void ipc_rfs_send_io_confirm_for_nv_read_item(struct ipc_client *client,
-    struct ipc_message_info *info);
+char *ipc_nv_data_md5_calculate(const char *path, const char *secret,
+    size_t size, size_t chunk_size);
+int ipc_nv_data_path_check(struct ipc_client *client);
+int ipc_nv_data_md5_path_check(struct ipc_client *client);
+int ipc_nv_data_backup_path_check(struct ipc_client *client);
+int ipc_nv_data_backup_md5_path_check(struct ipc_client *client);
+int ipc_nv_data_check(struct ipc_client *client);
+int ipc_nv_data_backup_check(struct ipc_client *client);
+int ipc_nv_data_backup(struct ipc_client *client);
+int ipc_nv_data_restore(struct ipc_client *client);
+void *ipc_nv_data_load(struct ipc_client *client);
+void *ipc_nv_data_read(struct ipc_client *client, size_t size, size_t offset);
+int ipc_nv_data_write(struct ipc_client *client, const void *data, size_t size,
+    size_t offset);
+void *ipc_rfs_nv_read_item_response_setup(const void *data, size_t size,
+    size_t offset);
 
 #endif
 
index f0aa05b..2c4d64b 100644 (file)
@@ -238,29 +238,16 @@ int xmm6160_nv_data_send(struct ipc_client *client, int device_fd,
     if (client == NULL || (device_fd < 0 && device_address == NULL))
         return -1;
 
-    rc = nv_data_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data");
-
-    rc = nv_data_md5_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data md5 failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data md5");
+    nv_size = ipc_client_nv_data_size(client);
 
-    nv_data = file_data_read(ipc_client_nv_data_path(client), ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+    nv_data = ipc_nv_data_load(client);
     if (nv_data == NULL) {
-        ipc_client_log(client, "Reading nv_data failed");
+        ipc_client_log(client, "Loading nv_data failed");
         goto error;
     }
-    ipc_client_log(client, "Read nv_data");
+    ipc_client_log(client, "Loaded nv_data");
 
     p = (unsigned char *) nv_data;
-    nv_size = ipc_client_nv_data_size(client);
 
     if (device_address != NULL) {
         memcpy(device_address, p, nv_size);
index d53ff11..747ebd1 100644 (file)
@@ -547,28 +547,14 @@ int xmm6260_hsic_nv_data_send(struct ipc_client *client, int device_fd)
     if (client == NULL || device_fd < 0)
         return -1;
 
-    rc = nv_data_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data");
-
-    rc = nv_data_md5_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data md5 failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data md5");
+    nv_size = ipc_client_nv_data_size(client);
 
-    nv_data = file_data_read(ipc_client_nv_data_path(client), ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+    nv_data = ipc_nv_data_load(client);
     if (nv_data == NULL) {
-        ipc_client_log(client, "Reading nv_data failed");
+        ipc_client_log(client, "Loading nv_data failed");
         goto error;
     }
-    ipc_client_log(client, "Read nv_data");
-
-    nv_size = ipc_client_nv_data_size(client);
+    ipc_client_log(client, "Loaded nv_data");
 
     rc = xmm6260_hsic_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
     if (rc < 0)
index 06a2b90..a14fd20 100644 (file)
@@ -597,28 +597,14 @@ int xmm6260_mipi_nv_data_send(struct ipc_client *client, int device_fd)
     if (client == NULL || device_fd < 0)
         return -1;
 
-    rc = nv_data_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data");
-
-    rc = nv_data_md5_check(client);
-    if (rc < 0) {
-        ipc_client_log(client, "Checking nv_data md5 failed");
-        goto error;
-    }
-    ipc_client_log(client, "Checked nv_data md5");
+    nv_size = ipc_client_nv_data_size(client);
 
-    nv_data = file_data_read(ipc_client_nv_data_path(client), ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+    nv_data = ipc_nv_data_load(client);
     if (nv_data == NULL) {
-        ipc_client_log(client, "Reading nv_data failed");
+        ipc_client_log(client, "Loading nv_data failed");
         goto error;
     }
-    ipc_client_log(client, "Read nv_data");
-
-    nv_size = ipc_client_nv_data_size(client);
+    ipc_client_log(client, "Loaded nv_data");
 
     rc = xmm6260_mipi_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
     if (rc < 0)
index 5b56e6c..7d17b5a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of libsamsung-ipc.
  *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr>
  *
  * libsamsung-ipc is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "ipc.h"
 #include "utils.h"
 
-#define MD5_STRING_SIZE                         MD5_DIGEST_LENGTH * 2 + 1
-
-void md5hash2string(char *out, unsigned char *in)
+char *ipc_nv_data_md5_calculate(const char *path, const char *secret,
+    size_t size, size_t chunk_size)
 {
-    int i;
-
-    for (i = 0; i < MD5_DIGEST_LENGTH; i++)
-    {
-        /* After the first iteration, we override \0. */
-        if (*in < 0x10)
-            sprintf(out, "0%x", *in);
-        else
-            sprintf(out, "%x", *in);
-
-        in++;
-        out += 2;
-    }
-}
+    void *data = NULL;
+    char *md5_string = NULL;
+    unsigned char md5_hash[MD5_DIGEST_LENGTH] = { 0 };
+    MD5_CTX ctx;
+    int rc;
 
-void nv_data_generate(struct ipc_client *client)
-{
-    return;
-}
+    if (secret == NULL)
+        return NULL;
 
-void nv_data_md5_compute(void *data_p, int size, char *secret, void *hash)
-{
-    MD5_CTX ctx;
+    data = file_data_read(path, size, chunk_size, 0);
+    if (data == NULL)
+        return NULL;
 
     MD5_Init(&ctx);
-    MD5_Update(&ctx, data_p, size);
+    MD5_Update(&ctx, data, size);
     MD5_Update(&ctx, secret, strlen(secret));
-    MD5_Final(hash, &ctx);
+    MD5_Final((unsigned char *) &md5_hash, &ctx);
+
+    md5_string = data2string(&md5_hash, sizeof(md5_hash));
+
+    return md5_string;
 }
 
-void nv_data_md5_generate(struct ipc_client *client)
+int ipc_nv_data_path_check(struct ipc_client *client)
 {
-    uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH];
-    char *nv_data_md5_hash_string = NULL;
-    void *nv_data_p = NULL;
-    int fd;
+    struct stat st;
+    char *path;
+    size_t size;
     int rc;
 
-    ipc_client_log(client, "nv_data_md5_generate: enter");
-
-    ipc_client_log(client, "nv_data_md5_generate: generating MD5 hash");
-    nv_data_p = file_data_read(ipc_client_nv_data_path(client),
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
-    nv_data_md5_compute(nv_data_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
-    free(nv_data_p);
-
-    /* Alloc the memory for the md5 hash string. */
-    nv_data_md5_hash_string = malloc(MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
-
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
-
-    ipc_client_log(client, "nv_data_md5_generate: new MD5 hash is %s", nv_data_md5_hash_string);
+    if (client == NULL)
+        return -1;
 
-    ipc_client_log(client, "nv_data_md5_generate: writing MD5 hash");
+    path = ipc_client_nv_data_path(client);
+    size = ipc_client_nv_data_size(client);
+    if (path == NULL || size == 0)
+        return -1;
 
-    /* Write the MD5 hash in nv_data.bin.md5. */
-    fd = open(ipc_client_nv_data_md5_path(client), O_RDWR | O_CREAT | O_TRUNC, 0644);
-    if (fd < 0)
-    {
-        ipc_client_log(client, "nv_data_md5_generate: fd open failed");
-        goto exit;
+    rc = stat(path, &st);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data path failed");
+        return -1;
     }
 
-    rc = write(fd, nv_data_md5_hash_string, MD5_STRING_SIZE);
-    if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_md5_generate: failed to write MD5 hash to file");
-        close(fd);
-        goto exit;
+    if (st.st_size != size) {
+        ipc_client_log(client, "Checking nv_data size failed");
+        return -1;
     }
 
-    close(fd);
-
-exit:
-    if (nv_data_md5_hash_string != NULL)
-        free(nv_data_md5_hash_string);
+    ipc_client_log(client, "Checked nv_data path");
 
-    ipc_client_log(client, "nv_data_md5_generate: exit");
+    return 0;
 }
 
-void nv_data_backup_create(struct ipc_client *client)
+int ipc_nv_data_md5_path_check(struct ipc_client *client)
 {
-    uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH];
-    char *nv_data_md5_hash_string = NULL;
-    char *nv_data_md5_hash_read = NULL;
-    int nv_data_write_tries = 0;
-
-    struct stat nv_stat;
-    void *nv_data_p = NULL;
-    void *nv_data_bak_p = NULL;
-    uint8_t data;
-
-    int fd;
+    struct stat st;
+    char *md5_path;
     int rc;
-    int i;
 
-    ipc_client_log(client, "nv_data_backup_create: enter");
+    if (client == NULL)
+        return -1;
 
-    if (stat(ipc_client_nv_data_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: nv_data.bin missing");
-        nv_data_generate(client);
-    }
+    md5_path = ipc_client_nv_data_md5_path(client);
+    if (md5_path == NULL)
+        return -1;
 
-    if (nv_stat.st_size != ipc_client_nv_data_size(client))
-    {
-        ipc_client_log(client, "nv_data_backup_create: wrong nv_data.bin size");
-        nv_data_generate(client);
-        return;
+    rc = stat(md5_path, &st);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data md5 path failed");
+        return -1;
     }
 
-    if (stat(ipc_client_nv_data_md5_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: nv_data.bin.md5 missing");
-        nv_data_generate(client);
-        return;
+    if (st.st_size < 2 * sizeof(char) * MD5_DIGEST_LENGTH) {
+        ipc_client_log(client, "Checking nv_data md5 size failed");
+        return -1;
     }
 
-    /* Alloc the memory for the md5 hashes strings. */
-    nv_data_md5_hash_string = malloc(MD5_STRING_SIZE);
-    nv_data_md5_hash_read = malloc(MD5_STRING_SIZE);
+    ipc_client_log(client, "Checked nv_data md5 path");
 
-    memset(nv_data_md5_hash_read, 0, MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
+    return 0;
+}
 
-    /* Read the content of the backup file. */
-    nv_data_p = file_data_read(ipc_client_nv_data_path(client),
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+int ipc_nv_data_backup_path_check(struct ipc_client *client)
+{
+    struct stat st;
+    char *backup_path;
+    size_t size;
+    int rc;
 
-    /* Compute the backup file MD5 hash. */
-    nv_data_md5_compute(nv_data_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
+    if (client == NULL)
+        return -1;
 
-    /* Read the stored backup file MD5 hash. */
-    fd = open(ipc_client_nv_data_md5_path(client), O_RDONLY);
-    if (fd < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: failed to openstored backup file with MD5 hash");
-        goto exit;
-    }
+    backup_path = ipc_client_nv_data_backup_path(client);
+    size = ipc_client_nv_data_size(client);
+    if (backup_path == NULL || size == 0)
+        return -1;
 
-    rc = read(fd, nv_data_md5_hash_read, MD5_STRING_SIZE);
-    if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: failed to read MD5 hash from backup file");
-        close(fd);
-        goto exit;
+    rc = stat(backup_path, &st);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup path failed");
+        return -1;
     }
 
-    close(fd);
+    if (st.st_size != size) {
+        ipc_client_log(client, "Checking nv_data backup size failed");
+        return -1;
+    }
 
-    /* Add 0x0 to end the string: not sure this is always part of the file. */
-    nv_data_md5_hash_read[MD5_STRING_SIZE - 1] = '\0';
+    ipc_client_log(client, "Checked nv_data backup path");
 
-    ipc_client_log(client, "nv_data_backup_create: backup file computed MD5: %s read MD5: %s",
-        nv_data_md5_hash_string, nv_data_md5_hash_read);
+    return 0;
+}
 
-    if (strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: MD5 hash mismatch on backup file");
-        ipc_client_log(client, "nv_data_backup_create: Consider the computed one as correct");
+int ipc_nv_data_backup_md5_path_check(struct ipc_client *client)
+{
+    struct stat st;
+    char *backup_md5_path;
+    int rc;
 
-        fd = open(ipc_client_nv_data_md5_path(client), O_WRONLY);
-        if (fd < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_create: failed to open file with MD5 hash of data file");
-            goto exit;
-        }
+    if (client == NULL)
+        return -1;
 
-        rc = read(fd, nv_data_md5_hash_string, MD5_STRING_SIZE);
-        if (rc < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_create: failed to read MD5 hash for data file from file");
-            goto exit;
-        }
+    backup_md5_path = ipc_client_nv_data_backup_md5_path(client);
+    if (backup_md5_path == NULL)
+        return -1;
 
-        close(fd);
+    rc = stat(backup_md5_path, &st);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup md5 path failed");
+        return -1;
+    }
 
-        /*
-        nv_data_backup_generate(client);
-        nv_data_backup_create(client);
-        return;
-        */
+    if (st.st_size < 2 * sizeof(char) * MD5_DIGEST_LENGTH) {
+        ipc_client_log(client, "Checking nv_data backup md5 size failed");
+        return -1;
     }
 
-    /* Assume the read string is the computated one */
-    memcpy(nv_data_md5_hash_read, nv_data_md5_hash_string, MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
+    ipc_client_log(client, "Checked nv_data backup md5 path");
 
-nv_data_backup_create_write:
-   while (nv_data_write_tries < 5)
-    {
-        ipc_client_log(client, "nv_data_backup_create: .nv_data.bak write try #%d", nv_data_write_tries + 1);
+    return 0;
+}
 
-        fd = open(ipc_client_nv_data_backup_path(client), O_RDWR | O_CREAT | O_TRUNC, 0644);
-        if (fd < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_create: negative fd while opening /efs/.nv_data.bak, error: %s", strerror(errno));
-            nv_data_write_tries++;
-            continue;
-        }
+int ipc_nv_data_check(struct ipc_client *client)
+{
+    char *path;
+    char *md5_path;
+    char *secret;
+    size_t size;
+    size_t chunk_size;
+    char *md5_string = NULL;
+    void *buffer = NULL;
+    char *string = NULL;
+    size_t length;
+    int rc;
 
-        rc = write(fd, nv_data_p, ipc_client_nv_data_size(client));
-        if (rc < ipc_client_nv_data_size(client))
-        {
-            ipc_client_log(client, "nv_data_backup_create: wrote less (%d) than what we expected (%d) on /efs/.nv_data.bak, error: %s", strerror(errno));
-            close(fd);
-            nv_data_write_tries++;
-            continue;
-        }
+    if (client == NULL)
+        return -1;
 
-        close(fd);
-        break;
-    }
+    path = ipc_client_nv_data_path(client);
+    md5_path = ipc_client_nv_data_md5_path(client);
+    secret = ipc_client_nv_data_secret(client);
+    size = ipc_client_nv_data_size(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || md5_path == NULL || secret == NULL || size == 0 || chunk_size == 0)
+        return -1;
 
-    if (nv_data_write_tries == 5)
-    {
-        ipc_client_log(client, "nv_data_backup_create: writing nv_data.bin to .nv_data.bak failed too many times");
-        unlink(ipc_client_nv_data_backup_path(client));
-        goto exit;
+    rc = ipc_nv_data_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data path failed");
+        goto error;
     }
 
-    /* Read the newly-written .nv_data.bak. */
-    nv_data_bak_p = file_data_read(ipc_client_nv_data_backup_path(client), 
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+    rc = ipc_nv_data_md5_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data md5 path failed");
+        goto error;
+    }
 
-    /* Compute the MD5 hash for nv_data.bin. */
-    nv_data_md5_compute(nv_data_bak_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
+    md5_string = ipc_nv_data_md5_calculate(path, secret, size, chunk_size);
+    if (md5_string == NULL) {
+        ipc_client_log(client, "Calculating nv_data md5 failed");
+        goto error;
+    }
+    ipc_client_log(client, "Calculated nv_data md5: %s", md5_string);
 
-    if (nv_data_bak_p != NULL)
-        free(nv_data_bak_p);
+    length = strlen(md5_string);
 
-    ipc_client_log(client, "nv_data_backup_create: written file computed MD5: %s read MD5: %s",
-        nv_data_md5_hash_string, nv_data_md5_hash_read);
+    buffer = file_data_read(md5_path, length, length, 0);
+    if (buffer == NULL) {
+        ipc_client_log(client, "Reading nv_data md5 failed");
+        goto error;
+    }
 
-    /* Make sure both hashes are the same. */
-    if (strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: MD5 hash mismatch on written file");
-        ipc_client_log(client, "nv_data_backup_create: Writing again");
+    string = strndup(buffer, length);
+    ipc_client_log(client, "Read nv_data md5: %s", string);
 
-        goto nv_data_backup_create_write;
+    rc = strncmp(md5_string, string, length);
+    if (rc != 0) {
+        ipc_client_log(client, "Matching nv_data md5 failed");
+        goto error;
     }
 
-    /* Write the MD5 hash in .nv_data.bak.md5. */
-    fd = open(ipc_client_nv_data_backup_md5_path(client), O_WRONLY | O_CREAT | O_TRUNC, 0644);
-    if (fd < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: failed to open MD5 hash file");
-        goto exit;
-    }
+    rc = 0;
+    goto complete;
 
-    rc = write(fd, nv_data_md5_hash_read, MD5_STRING_SIZE);
-    if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_create: failed to write MD5 hash to file");
-        close(fd);
-        goto exit;
-    }
-    close(fd);
-
-exit:
-    if (nv_data_p != NULL)
-        free(nv_data_p);
-    if (nv_data_md5_hash_string != NULL)
-        free(nv_data_md5_hash_string);
-    if (nv_data_md5_hash_read)
-        free(nv_data_md5_hash_read);
-
-    ipc_client_log(client, "nv_data_backup_create: exit");
-}
+error:
+    rc = -1;
 
-void nv_data_backup_restore(struct ipc_client *client)
-{
-    uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH];
-    char *nv_data_md5_hash_string = NULL;
-    char *nv_data_md5_hash_read = NULL;
-    int nv_data_write_tries = 0;
+complete:
+    if (string != NULL)
+        free(string);
+
+    if (buffer != NULL)
+        free(buffer);
 
-    struct stat nv_stat;
-    void *nv_data_p = NULL;
-    void *nv_data_bak_p = NULL;
-    uint8_t data;
+    if (md5_string != NULL)
+        free(md5_string);
+
+    return rc;
+}
 
-    int fd;
+int ipc_nv_data_backup_check(struct ipc_client *client)
+{
+    char *backup_path;
+    char *backup_md5_path;
+    char *secret;
+    size_t size;
+    size_t chunk_size;
+    char *backup_md5_string = NULL;
+    void *buffer = NULL;
+    char *string = NULL;
+    size_t length;
     int rc;
-    int i;
 
-    ipc_client_log(client, "nv_data_backup_restore: enter");
+    if (client == NULL)
+        return -1;
 
-    if (stat(ipc_client_nv_data_backup_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: .nv_data.bak missing");
-        nv_data_generate(client);
-        nv_data_backup_create(client);
-        return;
-    }
+    backup_path = ipc_client_nv_data_backup_path(client);
+    backup_md5_path = ipc_client_nv_data_backup_md5_path(client);
+    secret = ipc_client_nv_data_secret(client);
+    size = ipc_client_nv_data_size(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (backup_path == NULL || backup_md5_path == NULL || secret == NULL || size == 0 || chunk_size == 0)
+        return -1;
 
-    if (nv_stat.st_size != ipc_client_nv_data_size(client))
-    {
-        ipc_client_log(client, "nv_data_backup_restore: wrong .nv_data.bak size");
-        nv_data_generate(client);
-        nv_data_backup_create(client);
-        return;
+    rc = ipc_nv_data_backup_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup path failed");
+        goto error;
     }
 
-    if (stat(ipc_client_nv_data_backup_md5_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: .nv_data.bak.md5 missing");
-        nv_data_generate(client);
-        nv_data_backup_create(client);
-        return;
+    rc = ipc_nv_data_backup_md5_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup md5 path failed");
+        goto error;
     }
 
-    /* Alloc the memory for the md5 hashes strings. */
-    nv_data_md5_hash_string = malloc(MD5_STRING_SIZE);
-    nv_data_md5_hash_read = malloc(MD5_STRING_SIZE);
-
-    memset(nv_data_md5_hash_read, 0, MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
-
-    /* Read the content of the backup file. */
-    nv_data_bak_p = file_data_read(ipc_client_nv_data_backup_path(client),
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
+    backup_md5_string = ipc_nv_data_md5_calculate(backup_path, secret, size, chunk_size);
+    if (backup_md5_string == NULL) {
+        ipc_client_log(client, "Calculating nv_data backup md5 failed");
+        goto error;
+    }
+    ipc_client_log(client, "Calculated nv_data backup md5: %s", backup_md5_string);
 
-    /* Compute the backup file MD5 hash. */
-    nv_data_md5_compute(nv_data_bak_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
+    length = strlen(backup_md5_string);
 
-    /* Read the stored backup file MD5 hash. */
-    fd = open(ipc_client_nv_data_backup_md5_path(client), O_RDONLY);
-    rc = read(fd, nv_data_md5_hash_read, MD5_STRING_SIZE);
-    if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: Failed to read md5 hash for stored back file");
-        close(fd);
-        goto exit;
+    buffer = file_data_read(backup_md5_path, length, length, 0);
+    if (buffer == NULL) {
+        ipc_client_log(client, "Reading nv_data backup md5 failed");
+        goto error;
     }
 
-    close(fd);
-
-    /* Add 0x0 to end the string: not sure this is always part of the file. */
-    nv_data_md5_hash_read[MD5_STRING_SIZE - 1] = '\0';
+    string = strndup(buffer, length);
+    ipc_client_log(client, "Read nv_data backup md5: %s", string);
 
-    ipc_client_log(client, "nv_data_backup_restore: backup file computed MD5: %s read MD5: %s",
-        nv_data_md5_hash_string, nv_data_md5_hash_read);
+    rc = strncmp(backup_md5_string, string, length);
+    if (rc != 0) {
+        ipc_client_log(client, "Matching nv_data backup md5 failed");
+        goto error;
+    }
 
-    if (strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: MD5 hash mismatch on backup file");
-        ipc_client_log(client, "nv_data_backup_restore: Consider the computed one as correct");
+    rc = 0;
+    goto complete;
 
-        fd = open(ipc_client_nv_data_backup_md5_path(client), O_WRONLY);
-        if (fd < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_restore: failed to open MD5 hash backup file");
-            goto exit;
-        }
+error:
+    rc = -1;
 
-        rc = read(fd, nv_data_md5_hash_string, MD5_STRING_SIZE);
-        if (rc < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_restore: failed to read MD5 hash from backup file");
-            close(fd);
-            goto exit;
-        }
+complete:
+    if (string != NULL)
+        free(string);
 
-        close(fd);
+    if (buffer != NULL)
+        free(buffer);
 
-        /*
-        nv_data_backup_generate(client);
-        nv_data_backup_create(client);
-        return;
-        */
-    }
+    if (backup_md5_string != NULL)
+        free(backup_md5_string);
 
-    /* Assume the read string is the computated one */
-    memcpy(nv_data_md5_hash_read, nv_data_md5_hash_string, MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
+    return rc;
+}
 
-nv_data_backup_restore_write:
-   while (nv_data_write_tries < 5)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: nv_data.bin write try #%d", nv_data_write_tries + 1);
+int ipc_nv_data_backup(struct ipc_client *client)
+{
+    void *data = NULL;
+    char *path;
+    char *backup_path;
+    char *backup_md5_path;
+    char *secret;
+    size_t size;
+    size_t chunk_size;
+    char *md5_string = NULL;
+    size_t length;
+    int rc;
 
-        fd = open(ipc_client_nv_data_path(client), O_RDWR | O_CREAT | O_TRUNC, 0644);
-        if (fd < 0)
-        {
-            ipc_client_log(client, "nv_data_backup_restore: negative fd while opening /efs/nv_data.bin, error: %s", strerror(errno));
-            nv_data_write_tries++;
-            continue;
-        }
+    if (client == NULL)
+        return -1;
 
-        rc = write(fd, nv_data_bak_p, ipc_client_nv_data_size(client));
-        if (rc < ipc_client_nv_data_size(client))
-        {
-            ipc_client_log(client, "nv_data_backup_restore: wrote less (%d) than what we expected (%d) on /efs/nv_data.bin, error: %s", strerror(errno));
-            close(fd);
-            nv_data_write_tries++;
-            continue;
-        }
+    path = ipc_client_nv_data_path(client);
+    backup_path = ipc_client_nv_data_backup_path(client);
+    backup_md5_path = ipc_client_nv_data_backup_md5_path(client);
+    secret = ipc_client_nv_data_secret(client);
+    size = ipc_client_nv_data_size(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || backup_path == NULL || backup_md5_path == NULL || secret == NULL || size == 0 || chunk_size == 0)
+        return -1;
 
-        close(fd);
-        break;
+    rc = ipc_nv_data_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data path failed");
+        goto error;
     }
 
-    if (nv_data_write_tries == 5)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: writing the backup to nv_data.bin failed too many times");
-        unlink(ipc_client_nv_data_path(client));
-        goto exit;
+    data = file_data_read(path, size, chunk_size, 0);
+    if (data == NULL) {
+        ipc_client_log(client, "Reading nv_data failed");
+        goto error;
     }
 
-    /* Read the newly-written nv_data.bin. */
-    nv_data_p = file_data_read(ipc_client_nv_data_path(client),
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
-
-    /* Compute the MD5 hash for nv_data.bin. */
-    nv_data_md5_compute(nv_data_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
-
-    if (nv_data_p != NULL)
-    {
-        free(nv_data_p);
-        nv_data_p = NULL;
+    md5_string = ipc_nv_data_md5_calculate(path, secret, size, chunk_size);
+    if (md5_string == NULL) {
+        ipc_client_log(client, "Calculating nv_data md5 failed");
+        goto error;
     }
 
-    ipc_client_log(client, "nv_data_backup_restore: written file computed MD5: %s read MD5: %s",
-        nv_data_md5_hash_string, nv_data_md5_hash_read);
-
-    /* Make sure both hashes are the same. */
-    if (strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: MD5 hash mismatch on written file");
-        ipc_client_log(client, "nv_data_backup_restore: Writing again");
+    length = strlen(md5_string);
 
-        goto nv_data_backup_restore_write;
-    }
+    rc = unlink(backup_path);
+    if (rc < 0)
+        ipc_client_log(client, "Removing nv_data backup path failed");
 
-    /* Write the MD5 hash in nv_data.bin.md5. */
-    fd = open(ipc_client_nv_data_md5_path(client), O_WRONLY | O_CREAT | O_TRUNC, 0644);
-    if (fd < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: failed to open file with MD5 hash");
-        goto exit;
+    rc = file_data_write(backup_path, data, size, chunk_size, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data backup failed");
+        goto error;
     }
 
-    rc = write(fd, nv_data_md5_hash_read, MD5_STRING_SIZE);
+    rc = unlink(backup_md5_path);
     if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_backup_restore: failed to write MD5 hash to file");
-        close(fd);
-        goto exit;
-    }
-    close(fd);
-
-exit:
-    if (nv_data_bak_p != NULL)
-        free(nv_data_bak_p);
-    if (nv_data_md5_hash_string != NULL)
-        free(nv_data_md5_hash_string);
-    if (nv_data_md5_hash_read != NULL)
-        free(nv_data_md5_hash_read);
-
-    ipc_client_log(client, "nv_data_backup_restore: exit");
-}
-
-int nv_data_check(struct ipc_client *client)
-{
-    struct stat nv_stat;
-    int rc;
-
-    ipc_client_log(client, "nv_data_check: enter");
+        ipc_client_log(client, "Removing nv_data backup md5 path failed");
 
-    if (stat(ipc_client_nv_data_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_check: nv_data.bin missing");
-        nv_data_backup_restore(client);
-        stat(ipc_client_nv_data_path(client), &nv_stat);
+    rc = file_data_write(backup_md5_path, md5_string, length, length, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data backup md5 failed");
+        goto error;
     }
 
-    if (nv_stat.st_size != ipc_client_nv_data_size(client))
-    {
-        ipc_client_log(client, "nv_data_check: wrong nv_data.bin size");
-        nv_data_backup_restore(client);
-    }
+    ipc_client_log(client, "Backed up nv_data");
 
-    if (stat(ipc_client_nv_data_md5_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_check: nv_data.bin.md5 missing");
-        nv_data_backup_restore(client);
-    }
+    rc = 0;
+    goto complete;
 
-    if (stat(ipc_client_nv_data_backup_path(client), &nv_stat) < 0 || stat(ipc_client_nv_data_backup_md5_path(client), &nv_stat) < 0)
-    {
-        ipc_client_log(client, "nv_data_check: .nv_data.bak or .nv_data.bak.md5 missing");
-        nv_data_backup_create(client);
-    }
+error:
+    rc = -1;
 
-    ipc_client_log(client, "nv_data_check: everything should be alright");
-    ipc_client_log(client, "nv_data_check: exit");
+complete:
+    if (md5_string != NULL)
+        free(md5_string);
 
-    return 0;
+    if (data != NULL)
+        free(data);
+
+    return rc;
 }
 
-int nv_data_md5_check(struct ipc_client *client)
+int ipc_nv_data_restore(struct ipc_client *client)
 {
-    struct stat nv_stat;
-    uint8_t nv_data_md5_hash[MD5_DIGEST_LENGTH];
-    char *nv_data_md5_hash_string = NULL;
-    char *nv_data_md5_hash_read = NULL;
-    void *nv_data_p = NULL;
-    int fd;
+    void *data = NULL;
+    char *path;
+    char *md5_path;
+    char *backup_path;
+    char *backup_md5_path;
+    char *secret;
+    size_t size;
+    size_t chunk_size;
+    size_t length;
     int rc;
-    uint8_t *data_p;
 
-    ipc_client_log(client, "nv_data_md5_check: enter");
+    if (client == NULL)
+        return -1;
 
-    nv_data_md5_hash_string = malloc(MD5_STRING_SIZE);
-    nv_data_md5_hash_read = malloc(MD5_STRING_SIZE);
+    path = ipc_client_nv_data_path(client);
+    md5_path = ipc_client_nv_data_md5_path(client);
+    backup_path = ipc_client_nv_data_backup_path(client);
+    backup_md5_path = ipc_client_nv_data_backup_md5_path(client);
+    secret = ipc_client_nv_data_secret(client);
+    size = ipc_client_nv_data_size(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || md5_path == NULL || backup_path == NULL || backup_md5_path == NULL || secret == NULL || size == 0 || chunk_size == 0)
+        return -1;
 
-    memset(nv_data_md5_hash_read, 0, MD5_STRING_SIZE);
-    memset(nv_data_md5_hash_string, 0, MD5_STRING_SIZE);
+    rc = ipc_nv_data_backup_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup failed");
+        goto error;
+    }
 
-    nv_data_p = file_data_read(ipc_client_nv_data_path(client),
-        ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
-    data_p = nv_data_p;
+    data = file_data_read(backup_path, size, chunk_size, 0);
+    if (data == NULL) {
+        ipc_client_log(client, "Reading nv_data backup failed");
+        goto error;
+    }
 
-    nv_data_md5_compute(data_p, ipc_client_nv_data_size(client), ipc_client_nv_data_secret(client), nv_data_md5_hash);
+    rc = unlink(path);
+    if (rc < 0)
+        ipc_client_log(client, "Removing nv_data path failed");
 
-    md5hash2string(nv_data_md5_hash_string, nv_data_md5_hash);
+    rc = file_data_write(path, data, size, chunk_size, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data failed");
+        goto error;
+    }
 
-    free(nv_data_p);
+    free(data);
+    data = NULL;
 
-    fd = open(ipc_client_nv_data_md5_path(client), O_RDONLY);
+    length = 2 * sizeof(char) * MD5_DIGEST_LENGTH;
 
-    /* Read the md5 stored in the file. */
-    rc = read(fd, nv_data_md5_hash_read, MD5_STRING_SIZE);
-    if (rc < 0)
-    {
-        ipc_client_log(client, "nv_data_md5_check: Can't read md5 hash from file");
-        return -1;
+    data = file_data_read(backup_md5_path, length, length, 0);
+    if (data == NULL) {
+        ipc_client_log(client, "Reading nv_data backup md5 failed");
+        goto error;
     }
 
-    /* Add 0x0 to end the string: not sure this is part of the file. */
-    nv_data_md5_hash_read[MD5_STRING_SIZE - 1] = '\0';
-
-    ipc_client_log(client, "nv_data_md5_check: computed MD5: %s read MD5: %s", 
-        nv_data_md5_hash_string, nv_data_md5_hash_read);
+    rc = unlink(md5_path);
+    if (rc < 0)
+        ipc_client_log(client, "Removing nv_data md5 path failed");
 
-    if (strcmp(nv_data_md5_hash_string, nv_data_md5_hash_read) != 0)
-    {
-        ipc_client_log(client, "nv_data_md5_check: MD5 hash mismatch");
-        nv_data_backup_restore(client);
+    rc = file_data_write(md5_path, data, length, length, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data md5 failed");
+        goto error;
     }
 
-    if (nv_data_md5_hash_string != NULL)
-        free(nv_data_md5_hash_string);
-    if (nv_data_md5_hash_read != NULL)
-        free(nv_data_md5_hash_read);
+    ipc_client_log(client, "Restored nv_data");
 
-    ipc_client_log(client, "nv_data_md5_check: exit");
+    rc = 0;
+    goto complete;
 
-    return 0;
+error:
+    rc = -1;
+
+complete:
+    if (data != NULL)
+        free(data);
+
+    return rc;
 }
 
-int nv_data_read(struct ipc_client *client, int offset, int length, char *buf)
+void *ipc_nv_data_load(struct ipc_client *client)
 {
-    int fd;
+    void *data;
+    char *path;
+    size_t size;
+    size_t chunk_size;
     int rc;
 
-    ipc_client_log(client, "nv_data_read: enter");
+    if (client == NULL)
+        return NULL;
 
-    if (offset < 0 || length <= 0) {
-        ipc_client_log(client, "nv_data_read: offset < 0 or length <= 0");
-        return -1;
-    }
+    path = ipc_client_nv_data_path(client);
+    size = ipc_client_nv_data_size(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || size == 0 || chunk_size == 0)
+        return NULL;
 
-    if (buf == NULL) {
-        ipc_client_log(client, "nv_data_read: provided output buf is NULL");
-        return -1;
-    }
+    rc = ipc_nv_data_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data failed");
 
-    if (nv_data_check(client) < 0)
-        return -1;
+        rc = ipc_nv_data_restore(client);
+        if (rc < 0) {
+            ipc_client_log(client, "Restoring nv_data failed");
+            return NULL;
+        }
 
-    fd = open(ipc_client_nv_data_path(client), O_RDONLY);
-    if (fd < 0) {
-        ipc_client_log(client, "nv_data_read: nv_data file fd is negative");
-        return -1;
+        rc = ipc_nv_data_check(client);
+        if (rc < 0) {
+            ipc_client_log(client, "Checking nv_data failed");
+            return NULL;
+        }
     }
 
-    lseek(fd, offset, SEEK_SET);
+    rc = ipc_nv_data_backup_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data backup path failed");
 
-    rc = read(fd, buf, length);
-    if (rc < length) {
-        ipc_client_log(client, "nv_data_read: read less than what we expected");
-        return -1;
+        rc = ipc_nv_data_backup(client);
+        if (rc < 0)
+            ipc_client_log(client, "Backing up nv_data failed");
     }
 
-    ipc_client_log(client, "nv_data_read: exit");
+    data = file_data_read(path, size, chunk_size, 0);
+    if (data == NULL) {
+        ipc_client_log(client, "Reading nv_data failed");
+        return NULL;
+    }
 
-    return 0;
+    return data;
 }
 
-int nv_data_write(struct ipc_client *client, int offset, int length, char *buf)
+void *ipc_nv_data_read(struct ipc_client *client, size_t size, size_t offset)
 {
-    int fd;
+    void *data;
+    char *path;
+    size_t chunk_size;
     int rc;
 
-    ipc_client_log(client, "nv_data_write: enter");
+    if (client == NULL)
+        return NULL;
 
-    if (offset < 0 || length <= 0) {
-        ipc_client_log(client, "nv_data_write: offset or length <= 0");
-        return -1;
-    }
+    path = ipc_client_nv_data_path(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || chunk_size == 0)
+        return NULL;
 
-    if (buf == NULL) {
-        ipc_client_log(client, "nv_data_write: provided input buf is NULL");
-        return -1;
+    rc = ipc_nv_data_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data path failed");
+        return NULL;
     }
 
-    if (nv_data_check(client) < 0)
-        return -1;
-
-    fd = open(ipc_client_nv_data_path(client), O_WRONLY);
-    if (fd < 0) {
-        ipc_client_log(client, "nv_data_write: nv_data file fd is negative");
-        return -1;
+    data = file_data_read(path, size, chunk_size, offset);
+    if (data == NULL) {
+        ipc_client_log(client, "Reading nv_data failed");
+        return NULL;
     }
 
-    lseek(fd, offset, SEEK_SET);
+    return data;
+}
 
-    rc = write(fd, buf, length);
+int ipc_nv_data_write(struct ipc_client *client, const void *data, size_t size,
+    size_t offset)
+{
+    char *path;
+    char *md5_path;
+    char *secret;
+    size_t chunk_size;
+    char *md5_string = NULL;
+    size_t length;
+    int rc;
 
-    close(fd);
+    if (client == NULL)
+        return -1;
 
-    if (rc < length) {
-        ipc_client_log(client, "nv_data_write: wrote less (%d) than what we expected (%d), error: %s, restoring backup", rc, length, strerror(errno));
-        nv_data_backup_restore(client);
+    path = ipc_client_nv_data_path(client);
+    md5_path = ipc_client_nv_data_md5_path(client);
+    secret = ipc_client_nv_data_secret(client);
+    chunk_size = ipc_client_nv_data_chunk_size(client);
+    if (path == NULL || md5_path == NULL || secret == NULL || chunk_size == 0)
         return -1;
+
+    rc = ipc_nv_data_path_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data path failed");
+        goto error;
     }
 
-    ipc_client_log(client, "nv_data_write: writing new md5sum");
-    nv_data_md5_generate(client);
+    rc = file_data_write(path, data, size, chunk_size, offset);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data failed");
+        goto error;
+    }
 
-    ipc_client_log(client, "nv_data_write: exit");
+    size = ipc_client_nv_data_size(client);
+    if (size == 0)
+        goto error;
 
-    return 0;
-}
+    md5_string = ipc_nv_data_md5_calculate(path, secret, size, chunk_size);
+    if (md5_string == NULL) {
+        ipc_client_log(client, "Calculating nv_data md5 failed");
+        goto error;
+    }
 
-void ipc_rfs_send_io_confirm_for_nv_read_item(struct ipc_client *client,
-    struct ipc_message_info *info)
-{
-    struct ipc_rfs_nv_read_item_data *rfs_io = (struct ipc_rfs_nv_read_item_data *) info->data;
-    struct ipc_rfs_nv_read_item_confirm_header *rfs_io_conf;
-    void *rfs_data;
-    int rc;
+    length = strlen(md5_string);
 
-    if (rfs_io == NULL)
-    {
-        ipc_client_log(client, "ERROR: Request message is invalid: aseq = %i", info->aseq);
-        return;
+    rc = unlink(md5_path);
+    if (rc < 0) {
+        ipc_client_log(client, "Removing nv_data md5 path failed");
+        goto error;
     }
 
-    rfs_io_conf = malloc(rfs_io->length + sizeof(struct ipc_rfs_nv_read_item_confirm_header));
-    memset(rfs_io_conf, 0, rfs_io->length + sizeof(struct ipc_rfs_nv_read_item_confirm_header));
-    rfs_data = rfs_io_conf + sizeof(struct ipc_rfs_nv_read_item_confirm_header);
+    rc = file_data_write(md5_path, md5_string, length, length, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Writing nv_data md5 failed");
+        goto error;
+    }
 
-    ipc_client_log(client, "Asked to read 0x%x bytes at offset 0x%x", rfs_io->length, rfs_io->offset);
-    rc = nv_data_read(client, rfs_io->offset, rfs_io->length, rfs_data);
+    rc = 0;
+    goto complete;
 
-#ifdef DEBUG
-    ipc_client_log(client, "Read rfs_data dump:");
-    ipc_client_hex_dump(client, rfs_data, rfs_io->length);
-#endif
+error:
+    rc = -1;
 
-    ipc_client_log(client, "Preparing RFS IO Confirm message (rc is %d)", rc);
-    rfs_io_conf->confirm = rc < 0 ? 0 : 1;
-    rfs_io_conf->offset = rfs_io->offset;
-    rfs_io_conf->length = rfs_io->length;
+complete:
+    if (md5_string != NULL)
+        free(md5_string);
 
-    ipc_client_send(client, IPC_RFS_NV_READ_ITEM, 0, (unsigned char *) rfs_io_conf,
-                    rfs_io->length + sizeof(struct ipc_rfs_nv_read_item_confirm_header), info->aseq);
-    free(rfs_io_conf);
+    return rc;
 }
 
-void ipc_rfs_send_io_confirm_for_nv_write_item(struct ipc_client *client,
-    struct ipc_message_info *info)
+void *ipc_rfs_nv_read_item_response_setup(const void *data, size_t size,
+    size_t offset)
 {
-    struct ipc_rfs_nv_read_item_confirm_header *rfs_io = (struct ipc_rfs_nv_read_item_confirm_header *) info->data;
-    struct ipc_rfs_nv_write_item_confirm_data *rfs_io_conf;
-    void *rfs_data;
-    int rc;
+    struct ipc_rfs_nv_read_item_response_header *header;
+    void *buffer;
+    size_t length;
+    unsigned char confirm;
+    unsigned char *p;
 
-    if (rfs_io == NULL)
-    {
-        ipc_client_log(client, "ERROR: Request message is invalid: aseq = %i", info->aseq);
-        return;
+    if (data != NULL && size > 0) {
+        length = sizeof(struct ipc_rfs_nv_read_item_response_header) + size;
+        confirm = 1;
+    } else {
+        length = sizeof(struct ipc_rfs_nv_read_item_response_header);
+        size = 0;
+        offset = 0;
+        confirm = 0;
     }
 
-    rfs_data = info->data + sizeof(struct ipc_rfs_nv_read_item_confirm_header);
+    buffer = calloc(1, length);
 
-#ifdef DEBUG
-    ipc_client_log(client, "Write rfs_data dump:");
-    ipc_client_hex_dump(client, rfs_data, rfs_io->length);
-#endif
+    header = (struct ipc_rfs_nv_read_item_response_header *) buffer;
+    header->confirm = confirm;
+    header->offset = (unsigned int) offset;
+    header->length = (unsigned int) size;
 
-    ipc_client_log(client, "Asked to write 0x%x bytes at offset 0x%x", rfs_io->length, rfs_io->offset);
-    rc = nv_data_write(client, rfs_io->offset, rfs_io->length, rfs_data);
+    if (data != NULL && size > 0) {
+        p = (unsigned char *) buffer;
+        p += sizeof(struct ipc_rfs_nv_read_item_response_header);
 
-    ipc_client_log(client, "Sending RFS IO Confirm message (rc is %d)", rc);
-    rfs_io_conf = (struct ipc_rfs_nv_write_item_confirm_data *) malloc(sizeof(struct ipc_rfs_nv_write_item_confirm_data));
-    rfs_io_conf->confirm = rc < 0 ? 0 : 1;
-    rfs_io_conf->offset = rfs_io->offset;
-    rfs_io_conf->length = rfs_io->length;
+        memcpy(p, data, size);
+    }
 
-    ipc_client_send(client, IPC_RFS_NV_WRITE_ITEM, 0, (unsigned char *) rfs_io_conf,
-                    sizeof(struct ipc_rfs_nv_write_item_confirm_data), info->aseq);
-    free(rfs_io_conf);
+    return buffer;
 }
 
 // vim:ts=4:sw=4:expandtab