rmtfs: Initial rmtfs implementation

The rmtfs tool pushlishes the two QMI services "rmtfs" and "rfsa", and
implements the necessary requests for rmtfs that's needed to boot the
modem subsystem on a Qualcomm based board.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
Bjorn Andersson
2016-02-07 09:30:33 -08:00
parent 1e0cc246ed
commit 1f12cea75b
11 changed files with 1948 additions and 0 deletions

17
Makefile Normal file
View File

@@ -0,0 +1,17 @@
OUT := rmtfs
CFLAGS := -Wall -g -I../qrtr/lib
LDFLAGS := -L../qrtr -lqrtr
SRCS := qmi_rmtfs.c qmi_tlv.c rmtfs.c sharedmem.c storage.c util.c
OBJS := $(SRCS:.c=.o)
$(OUT): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
test: $(OUT)
./$(OUT)
clean:
rm -f $(OUT) $(OBJS)

600
qmi_rmtfs.c Normal file

File diff suppressed because it is too large Load Diff

196
qmi_rmtfs.h Normal file
View File

@@ -0,0 +1,196 @@
#ifndef __QMI_RMTFS_H__
#define __QMI_RMTFS_H__
#include <stdint.h>
#include <stdlib.h>
struct qmi_tlv;
struct qmi_tlv *qmi_tlv_init(unsigned txn, unsigned msg_id);
struct qmi_tlv *qmi_tlv_decode(void *buf, size_t len, unsigned *txn);
void *qmi_tlv_encode(struct qmi_tlv *tlv, size_t *len);
void qmi_tlv_free(struct qmi_tlv *tlv);
void *qmi_tlv_get(struct qmi_tlv *tlv, unsigned id, size_t *len);
void *qmi_tlv_get_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, size_t *len, size_t *size);
int qmi_tlv_set(struct qmi_tlv *tlv, unsigned id, void *buf, size_t len);
int qmi_tlv_set_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, void *buf, size_t len, size_t size);
#define QMI_RMTFS_RESULT_SUCCESS 0
#define QMI_RMTFS_RESULT_FAILURE 1
#define QMI_RMTFS_ERR_NONE 0
#define QMI_RMTFS_ERR_INTERNAL 1
#define QMI_RMTFS_ERR_MALFORMED_MSG 2
#define QMI_RMTFS_OPEN 1
#define QMI_RMTFS_CLOSE 2
#define QMI_RMTFS_RW_IOVEC 3
#define QMI_RMTFS_ALLOC_BUFF 4
#define QMI_RMTFS_GET_DEV_ERROR 5
#define QMI_RMTFS_FORCE_SYNC_IND 6
struct rmtfs_qmi_result {
uint16_t result;
uint16_t error;
};
struct rmtfs_iovec_entry {
uint32_t sector_addr;
uint32_t phys_offset;
uint32_t num_sector;
};
struct rmtfs_open_req;
struct rmtfs_open_resp;
struct rmtfs_close_req;
struct rmtfs_close_resp;
struct rmtfs_iovec_req;
struct rmtfs_iovec_resp;
struct rmtfs_alloc_buf_req;
struct rmtfs_alloc_buf_resp;
struct rmtfs_dev_error_req;
struct rmtfs_dev_error_resp;
struct rmtfs_force_sync;
/*
* rmtfs_open_req message
*/
struct rmtfs_open_req *rmtfs_open_req_alloc(unsigned txn);
struct rmtfs_open_req *rmtfs_open_req_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_open_req_encode(struct rmtfs_open_req *open_req, size_t *len);
void rmtfs_open_req_free(struct rmtfs_open_req *open_req);
int rmtfs_open_req_set_path(struct rmtfs_open_req *open_req, char *buf, size_t len);
int rmtfs_open_req_get_path(struct rmtfs_open_req *open_req, char *buf, size_t buflen);
/*
* rmtfs_open_resp message
*/
struct rmtfs_open_resp *rmtfs_open_resp_alloc(unsigned txn);
struct rmtfs_open_resp *rmtfs_open_resp_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_open_resp_encode(struct rmtfs_open_resp *open_resp, size_t *len);
void rmtfs_open_resp_free(struct rmtfs_open_resp *open_resp);
int rmtfs_open_resp_set_result(struct rmtfs_open_resp *open_resp, struct rmtfs_qmi_result *val);
struct rmtfs_qmi_result *rmtfs_open_resp_get_result(struct rmtfs_open_resp *open_resp);
int rmtfs_open_resp_set_caller_id(struct rmtfs_open_resp *open_resp, uint32_t val);
int rmtfs_open_resp_get_caller_id(struct rmtfs_open_resp *open_resp, uint32_t *val);
/*
* rmtfs_close_req message
*/
struct rmtfs_close_req *rmtfs_close_req_alloc(unsigned txn);
struct rmtfs_close_req *rmtfs_close_req_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_close_req_encode(struct rmtfs_close_req *close_req, size_t *len);
void rmtfs_close_req_free(struct rmtfs_close_req *close_req);
int rmtfs_close_req_set_caller_id(struct rmtfs_close_req *close_req, uint32_t val);
int rmtfs_close_req_get_caller_id(struct rmtfs_close_req *close_req, uint32_t *val);
/*
* rmtfs_close_resp message
*/
struct rmtfs_close_resp *rmtfs_close_resp_alloc(unsigned txn);
struct rmtfs_close_resp *rmtfs_close_resp_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_close_resp_encode(struct rmtfs_close_resp *close_resp, size_t *len);
void rmtfs_close_resp_free(struct rmtfs_close_resp *close_resp);
int rmtfs_close_resp_set_result(struct rmtfs_close_resp *close_resp, struct rmtfs_qmi_result *val);
struct rmtfs_qmi_result *rmtfs_close_resp_get_result(struct rmtfs_close_resp *close_resp);
/*
* rmtfs_iovec_req message
*/
struct rmtfs_iovec_req *rmtfs_iovec_req_alloc(unsigned txn);
struct rmtfs_iovec_req *rmtfs_iovec_req_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_iovec_req_encode(struct rmtfs_iovec_req *iovec_req, size_t *len);
void rmtfs_iovec_req_free(struct rmtfs_iovec_req *iovec_req);
int rmtfs_iovec_req_set_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t val);
int rmtfs_iovec_req_get_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t *val);
int rmtfs_iovec_req_set_direction(struct rmtfs_iovec_req *iovec_req, uint8_t val);
int rmtfs_iovec_req_get_direction(struct rmtfs_iovec_req *iovec_req, uint8_t *val);
int rmtfs_iovec_req_set_iovec(struct rmtfs_iovec_req *iovec_req, struct rmtfs_iovec_entry *val, size_t count);
struct rmtfs_iovec_entry *rmtfs_iovec_req_get_iovec(struct rmtfs_iovec_req *iovec_req, size_t *count);
int rmtfs_iovec_req_set_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t val);
int rmtfs_iovec_req_get_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t *val);
/*
* rmtfs_iovec_resp message
*/
struct rmtfs_iovec_resp *rmtfs_iovec_resp_alloc(unsigned txn);
struct rmtfs_iovec_resp *rmtfs_iovec_resp_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_iovec_resp_encode(struct rmtfs_iovec_resp *iovec_resp, size_t *len);
void rmtfs_iovec_resp_free(struct rmtfs_iovec_resp *iovec_resp);
int rmtfs_iovec_resp_set_result(struct rmtfs_iovec_resp *iovec_resp, struct rmtfs_qmi_result *val);
struct rmtfs_qmi_result *rmtfs_iovec_resp_get_result(struct rmtfs_iovec_resp *iovec_resp);
/*
* rmtfs_alloc_buf_req message
*/
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_alloc(unsigned txn);
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_alloc_buf_req_encode(struct rmtfs_alloc_buf_req *alloc_buf_req, size_t *len);
void rmtfs_alloc_buf_req_free(struct rmtfs_alloc_buf_req *alloc_buf_req);
int rmtfs_alloc_buf_req_set_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val);
int rmtfs_alloc_buf_req_get_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val);
int rmtfs_alloc_buf_req_set_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val);
int rmtfs_alloc_buf_req_get_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val);
/*
* rmtfs_alloc_buf_resp message
*/
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_alloc(unsigned txn);
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_alloc_buf_resp_encode(struct rmtfs_alloc_buf_resp *alloc_buf_resp, size_t *len);
void rmtfs_alloc_buf_resp_free(struct rmtfs_alloc_buf_resp *alloc_buf_resp);
int rmtfs_alloc_buf_resp_set_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp, struct rmtfs_qmi_result *val);
struct rmtfs_qmi_result *rmtfs_alloc_buf_resp_get_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp);
int rmtfs_alloc_buf_resp_set_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t val);
int rmtfs_alloc_buf_resp_get_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t *val);
/*
* rmtfs_dev_error_req message
*/
struct rmtfs_dev_error_req *rmtfs_dev_error_req_alloc(unsigned txn);
struct rmtfs_dev_error_req *rmtfs_dev_error_req_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_dev_error_req_encode(struct rmtfs_dev_error_req *dev_error_req, size_t *len);
void rmtfs_dev_error_req_free(struct rmtfs_dev_error_req *dev_error_req);
int rmtfs_dev_error_req_set_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t val);
int rmtfs_dev_error_req_get_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t *val);
/*
* rmtfs_dev_error_resp message
*/
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_alloc(unsigned txn);
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_dev_error_resp_encode(struct rmtfs_dev_error_resp *dev_error_resp, size_t *len);
void rmtfs_dev_error_resp_free(struct rmtfs_dev_error_resp *dev_error_resp);
int rmtfs_dev_error_resp_set_result(struct rmtfs_dev_error_resp *dev_error_resp, struct rmtfs_qmi_result *val);
struct rmtfs_qmi_result *rmtfs_dev_error_resp_get_result(struct rmtfs_dev_error_resp *dev_error_resp);
int rmtfs_dev_error_resp_set_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t val);
int rmtfs_dev_error_resp_get_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t *val);
/*
* rmtfs_force_sync message
*/
struct rmtfs_force_sync *rmtfs_force_sync_alloc(unsigned txn);
struct rmtfs_force_sync *rmtfs_force_sync_parse(void *buf, size_t len, unsigned *txn);
void *rmtfs_force_sync_encode(struct rmtfs_force_sync *force_sync, size_t *len);
void rmtfs_force_sync_free(struct rmtfs_force_sync *force_sync);
int rmtfs_force_sync_set_caller_id(struct rmtfs_force_sync *force_sync, uint32_t *val, size_t count);
uint32_t *rmtfs_force_sync_get_caller_id(struct rmtfs_force_sync *force_sync, size_t *count);
#endif

77
qmi_rmtfs.qmi Normal file
View File

@@ -0,0 +1,77 @@
package rmtfs;
const QMI_RMTFS_RESULT_SUCCESS = 0;
const QMI_RMTFS_RESULT_FAILURE = 1;
const QMI_RMTFS_ERR_NONE = 0;
const QMI_RMTFS_ERR_INTERNAL = 1;
const QMI_RMTFS_ERR_MALFORMED_MSG = 2;
const QMI_RMTFS_OPEN = 1;
const QMI_RMTFS_CLOSE = 2;
const QMI_RMTFS_RW_IOVEC = 3;
const QMI_RMTFS_ALLOC_BUFF = 4;
const QMI_RMTFS_GET_DEV_ERROR = 5;
const QMI_RMTFS_FORCE_SYNC_IND = 6;
struct qmi_result {
u16 result;
u16 error;
};
struct iovec_entry {
u32 sector_addr;
u32 phys_offset;
u32 num_sector;
};
message open_req {
required string path = 1;
} = 1;
message open_resp {
required qmi_result result = 2;
optional u32 caller_id = 0x10;
} = 1;
message close_req {
required u32 caller_id = 1;
} = 2;
message close_resp {
required qmi_result result = 2;
} = 2;
message iovec_req {
required u32 caller_id = 1;
required u8 direction = 2;
required iovec_entry iovec[] = 3;
required u8 is_force_sync = 4;
} = 3;
message iovec_resp {
required qmi_result result = 2;
} = 3;
message alloc_buf_req {
required u32 caller_id = 1;
required u32 buff_size = 2;
} = 4;
message alloc_buf_resp {
required qmi_result result = 2;
optional u64 buff_address = 0x10;
} = 4;
message dev_error_req {
required u32 caller_id = 1;
} = 5;
message dev_error_resp {
required qmi_result result = 2;
optional u8 status = 0x10;
} = 5;
message force_sync {
required u32 caller_id[] = 1;
} = 6;

234
qmi_tlv.c Normal file
View File

@@ -0,0 +1,234 @@
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "qmi_rmtfs.h"
#define QMI_PKT_TYPE_REQUEST 0
#define QMI_PKT_TYPE_RESPONSE 2
#define QMI_PKT_TYPE_CONTROL 4
struct qmi_packet {
uint8_t flags;
uint16_t txn_id;
uint16_t msg_id;
uint16_t msg_len;
uint8_t data[];
} __attribute__((__packed__));
struct qmi_tlv {
void *allocated;
void *buf;
size_t size;
int error;
};
struct qmi_tlv_item {
uint8_t key;
uint16_t len;
uint8_t data[];
} __attribute__((__packed__));
struct qmi_tlv *qmi_tlv_init(unsigned txn, unsigned msg_id)
{
struct qmi_packet *pkt;
struct qmi_tlv *tlv;
tlv = malloc(sizeof(struct qmi_tlv));
memset(tlv, 0, sizeof(struct qmi_tlv));
tlv->size = sizeof(struct qmi_packet);
tlv->allocated = malloc(tlv->size);
tlv->buf = tlv->allocated;
pkt = tlv->buf;
pkt->flags = QMI_PKT_TYPE_RESPONSE;
pkt->txn_id = txn;
pkt->msg_id = msg_id;
pkt->msg_len = 0;
return tlv;
}
struct qmi_tlv *qmi_tlv_decode(void *buf, size_t len, unsigned *txn)
{
struct qmi_packet *pkt = buf;
struct qmi_tlv *tlv;
tlv = malloc(sizeof(struct qmi_tlv));
memset(tlv, 0, sizeof(struct qmi_tlv));
tlv->buf = buf;
tlv->size = len;
if (txn)
*txn = pkt->txn_id;
return tlv;
}
void *qmi_tlv_encode(struct qmi_tlv *tlv, size_t *len)
{
struct qmi_packet *pkt;
if (!tlv || tlv->error)
return NULL;
pkt = tlv->buf;
pkt->msg_len = tlv->size - sizeof(struct qmi_packet);
*len = tlv->size;
return tlv->buf;
}
void qmi_tlv_free(struct qmi_tlv *tlv)
{
free(tlv->allocated);
free(tlv);
}
static struct qmi_tlv_item *qmi_tlv_get_item(struct qmi_tlv *tlv, unsigned id)
{
struct qmi_tlv_item *item;
struct qmi_packet *pkt;
unsigned offset = 0;
void *pkt_data;
pkt = tlv->buf;
pkt_data = pkt->data;
while (offset < tlv->size) {
item = pkt_data + offset;
if (item->key == id)
return pkt_data + offset;
offset += sizeof(struct qmi_tlv_item) + item->len;
}
return NULL;
}
void *qmi_tlv_get(struct qmi_tlv *tlv, unsigned id, size_t *len)
{
struct qmi_tlv_item *item;
item = qmi_tlv_get_item(tlv, id);
if (!item)
return NULL;
*len = item->len;
return item->data;
}
void *qmi_tlv_get_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, size_t *len, size_t *size)
{
struct qmi_tlv_item *item;
unsigned count;
void *ptr;
item = qmi_tlv_get_item(tlv, id);
if (!item)
return NULL;
ptr = item->data;
switch (len_size) {
case 4:
count = *(uint32_t*)ptr++;
break;
case 2:
count = *(uint16_t*)ptr++;
break;
case 1:
count = *(uint8_t*)ptr++;
break;
}
*len = count;
*size = (item->len - len_size) / count;
return ptr;
}
static struct qmi_tlv_item *qmi_tlv_alloc_item(struct qmi_tlv *tlv, unsigned id, size_t len)
{
struct qmi_tlv_item *item;
size_t new_size;
bool migrate;
void *newp;
/* If using user provided buffer, migrate data */
migrate = !tlv->allocated;
new_size = tlv->size + sizeof(struct qmi_tlv_item) + len;
newp = realloc(tlv->allocated, new_size);
if (!newp)
return NULL;
if (migrate)
memcpy(newp, tlv->buf, tlv->size);
item = newp + tlv->size;
item->key = id;
item->len = len;
tlv->buf = tlv->allocated = newp;
tlv->size = new_size;
return item;
}
int qmi_tlv_set(struct qmi_tlv *tlv, unsigned id, void *buf, size_t len)
{
struct qmi_tlv_item *item;
if (!tlv)
return -EINVAL;
item = qmi_tlv_alloc_item(tlv, id, len);
if (!item) {
tlv->error = ENOMEM;
return -ENOMEM;
}
memcpy(item->data, buf, len);
return 0;
}
int qmi_tlv_set_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, void *buf, size_t len, size_t size)
{
struct qmi_tlv_item *item;
size_t array_size;
void *ptr;
if (!tlv)
return -EINVAL;
array_size = len * size;
item = qmi_tlv_alloc_item(tlv, id, len_size + array_size);
if (!item) {
tlv->error = ENOMEM;
return -ENOMEM;
}
ptr = item->data;
switch (len_size) {
case 4:
*(uint32_t*)ptr++ = len;
break;
case 2:
*(uint16_t*)ptr++ = len;
break;
case 1:
*(uint8_t*)ptr++ = len;
break;
}
memcpy(ptr, buf, array_size);
return 0;
}

511
rmtfs.c Normal file

File diff suppressed because it is too large Load Diff

28
rmtfs.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef __RMTFS_H__
#define __RMTFS_H__
#include <stdint.h>
#include "qmi_rmtfs.h"
struct qmi_packet {
uint8_t flags;
uint16_t txn_id;
uint16_t msg_id;
uint16_t msg_len;
uint8_t data[];
} __attribute__((__packed__));
int rmtfs_mem_open(void);
void rmtfs_mem_close(void);
int64_t rmtfs_mem_alloc(size_t size);
void *rmtfs_mem_ptr(unsigned phys_address, size_t len);
void rmtfs_mem_free(void);
int storage_open(void);
int storage_get(unsigned node, const char *path);
int storage_put(unsigned node, int caller_id);
int storage_get_handle(unsigned node, int caller_id);
int storage_get_error(unsigned node, int caller_id);
void storage_close(void);
#endif

88
sharedmem.c Normal file
View File

@@ -0,0 +1,88 @@
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "rmtfs.h"
#define SHAREDMEM_BASE 0x0fd80000
#define SHAREDMEM_SIZE 0x180000
static uint64_t rmtfs_mem_address = SHAREDMEM_BASE;
static uint64_t rmtfs_mem_size = SHAREDMEM_SIZE;
static void *rmtfs_mem_base;
static bool rmtfs_mem_busy;
static int rmtfs_mem_fd;
int rmtfs_mem_open(void)
{
void *base;
int fd;
fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd < 0) {
fprintf(stderr, "failed to open /dev/mem\n");
return fd;
}
base = mmap(0, SHAREDMEM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, SHAREDMEM_BASE);
if (base == MAP_FAILED) {
fprintf(stderr, "failed to mmap: %s\n", strerror(errno));
return -errno;
}
rmtfs_mem_base = base;
rmtfs_mem_fd = fd;
return 0;
}
int64_t rmtfs_mem_alloc(size_t alloc_size)
{
if (rmtfs_mem_busy) {
fprintf(stderr, "[RMTFS] rmtfs shared memory already allocated\n");
return -EBUSY;
}
if (alloc_size > rmtfs_mem_size) {
fprintf(stderr,
"[RMTFS] rmtfs shared memory not large enough for allocation request 0x%zx vs 0x%lx\n",
alloc_size, rmtfs_mem_size);
return -EINVAL;
}
rmtfs_mem_busy = true;
return rmtfs_mem_address;
}
void rmtfs_mem_free(void)
{
rmtfs_mem_busy = false;
}
void *rmtfs_mem_ptr(unsigned phys_address, size_t len)
{
uint64_t start;
uint64_t end;
start = phys_address;
end = start + len;
if (start < rmtfs_mem_address || end > rmtfs_mem_address + rmtfs_mem_size)
return NULL;
return rmtfs_mem_base + phys_address - rmtfs_mem_address;
}
void rmtfs_mem_close(void)
{
munmap(rmtfs_mem_base, rmtfs_mem_size);
close(rmtfs_mem_fd);
rmtfs_mem_fd = -1;
rmtfs_mem_base = MAP_FAILED;
}

140
storage.c Normal file
View File

@@ -0,0 +1,140 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "rmtfs.h"
#define MAX_CALLERS 10
struct partition {
const char *path;
const char *actual;
};
struct caller {
unsigned id;
unsigned node;
int fd;
unsigned dev_error;
};
static const struct partition partition_table[] = {
{ "/boot/modem_fs1", "/boot/modem_fs1" },
{ "/boot/modem_fs2", "/boot/modem_fs2" },
{ "/boot/modem_fsg", "/boot/modem_fsg" },
{}
};
static struct caller caller_handles[MAX_CALLERS];
int storage_open(void)
{
int i;
for (i = 0; i < MAX_CALLERS; i++) {
caller_handles[i].id = i;
caller_handles[i].fd = -1;
}
return 0;
}
int storage_get(unsigned node, const char *path)
{
const struct partition *part;
struct caller *caller;
int saved_errno;
int fd;
int i;
for (part = partition_table; part->path; part++) {
if (strcmp(part->path, path) == 0)
goto found;
}
fprintf(stderr, "[RMTFS storage] request for unknown partition '%s', rejecting\n", path);
return -EPERM;
found:
for (i = 0; i < MAX_CALLERS; i++) {
if (caller_handles[i].fd == -1) {
caller = &caller_handles[i];
break;
}
}
if (!caller) {
fprintf(stderr, "[storage] out of free caller handles\n");
return -EBUSY;
}
fd = open(part->actual, O_RDWR);
if (fd < 0) {
saved_errno = errno;
fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
part->actual, part->path, strerror(-errno));
return -saved_errno;
}
caller->node = node;
caller->fd = fd;
return caller->id;
}
int storage_put(unsigned node, int caller_id)
{
struct caller *caller;
if (caller_id >= MAX_CALLERS)
return -EINVAL;
caller = &caller_handles[caller_id];
if (caller->node != node)
return -EINVAL;
close(caller->fd);
caller->fd = -1;
return 0;
}
int storage_get_handle(unsigned node, int caller_id)
{
struct caller *caller;
if (caller_id >= MAX_CALLERS)
return -EINVAL;
caller = &caller_handles[caller_id];
if (caller->node != node)
return -EINVAL;
return caller->fd;
}
int storage_get_error(unsigned node, int caller_id)
{
struct caller *caller;
if (caller_id >= MAX_CALLERS)
return -EINVAL;
caller = &caller_handles[caller_id];
if (caller->node != node)
return -EINVAL;
return caller->dev_error;
}
void storage_close(void)
{
int i;
for (i = 0; i < MAX_CALLERS; i++) {
if (caller_handles[i].fd >= 0)
close(caller_handles[i].fd);
}
}

48
util.c Normal file
View File

@@ -0,0 +1,48 @@
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include "util.h"
static uint8_t to_hex(uint8_t ch)
{
ch &= 0xf;
return ch <= 9 ? '0' + ch : 'a' + ch - 10;
}
void print_hex_dump(const char *prefix, const void *buf, size_t len)
{
const uint8_t *ptr = buf;
size_t linelen;
uint8_t ch;
char line[16 * 3 + 16 + 1];
int li;
int i;
int j;
for (i = 0; i < len; i += 16) {
linelen = MIN(16, len - i);
li = 0;
for (j = 0; j < linelen; j++) {
ch = ptr[i + j];
line[li++] = to_hex(ch >> 4);
line[li++] = to_hex(ch);
line[li++] = ' ';
}
for (; j < 16; j++) {
line[li++] = ' ';
line[li++] = ' ';
line[li++] = ' ';
}
for (j = 0; j < linelen; j++) {
ch = ptr[i + j];
line[li++] = isprint(ch) ? ch : '.';
}
line[li] = '\0';
printf("%s %04x: %s\n", prefix, i, line);
}
}

9
util.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __UTIL_H__
#define __UTIL_H__
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
void print_hex_dump(const char *prefix, const void *buf, size_t len);
#endif