From ec82c3a5350b8747e1c0a7a0393ab0374dd9fbd5 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Sat, 15 Feb 2014 12:03:32 +0100 Subject: rfs: Consistent coding style, cleanup and fresh new implementation Signed-off-by: Paul Kocialkowski --- include/rfs.h | 39 +- samsung-ipc/devices/xmm6160/xmm6160.c | 21 +- samsung-ipc/devices/xmm6260/xmm6260_hsic.c | 22 +- samsung-ipc/devices/xmm6260/xmm6260_mipi.c | 22 +- samsung-ipc/rfs.c | 1033 +++++++++++++--------------- 5 files changed, 514 insertions(+), 623 deletions(-) diff --git a/include/rfs.h b/include/rfs.h index d56f05a..acfd018 100644 --- a/include/rfs.h +++ b/include/rfs.h @@ -33,23 +33,23 @@ * 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 diff --git a/samsung-ipc/devices/xmm6160/xmm6160.c b/samsung-ipc/devices/xmm6160/xmm6160.c index f0aa05b..2c4d64b 100644 --- a/samsung-ipc/devices/xmm6160/xmm6160.c +++ b/samsung-ipc/devices/xmm6160/xmm6160.c @@ -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); diff --git a/samsung-ipc/devices/xmm6260/xmm6260_hsic.c b/samsung-ipc/devices/xmm6260/xmm6260_hsic.c index d53ff11..747ebd1 100644 --- a/samsung-ipc/devices/xmm6260/xmm6260_hsic.c +++ b/samsung-ipc/devices/xmm6260/xmm6260_hsic.c @@ -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) diff --git a/samsung-ipc/devices/xmm6260/xmm6260_mipi.c b/samsung-ipc/devices/xmm6260/xmm6260_mipi.c index 06a2b90..a14fd20 100644 --- a/samsung-ipc/devices/xmm6260/xmm6260_mipi.c +++ b/samsung-ipc/devices/xmm6260/xmm6260_mipi.c @@ -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) diff --git a/samsung-ipc/rfs.c b/samsung-ipc/rfs.c index 5b56e6c..7d17b5a 100644 --- a/samsung-ipc/rfs.c +++ b/samsung-ipc/rfs.c @@ -1,7 +1,7 @@ /* * This file is part of libsamsung-ipc. * - * Copyright (C) 2011 Paul Kocialkowski + * Copyright (C) 2011-2014 Paul Kocialkowski * * 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 @@ -33,732 +33,663 @@ #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 -- cgit v1.1