rmtfs/storage.c
Bjorn Andersson 1f12cea75b 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>
2016-02-07 09:32:14 -08:00

141 lines
2.4 KiB
C

#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);
}
}