commit 4ce9769862d0352900a9a0ec3e4e0b1611f512c7
parent dcb5fb757be749d2a067b98d7135184f8de05a7f
Author: Ambroise Vincent <ambroise.vincent@arm.com>
Date: Wed, 8 May 2019 16:05:33 +0100
[dev] Parse FIP ToC with serialization tools
Change-Id: Ifc5a1d244afee51dff12aefc4392b074c953f72e
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>
Diffstat:
M | drivers/devfip.c | | | 65 | ++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
1 file changed, 50 insertions(+), 15 deletions(-)
diff --git a/drivers/devfip.c b/drivers/devfip.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <deserialize.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
@@ -13,6 +14,8 @@
#define NR_FIPS 2
#define STOC_HEADER_NAME 4 /* strlen(TOC_HEADER_NAME); */
+#define STOC_HEADER 16 /* sizeof(fip_toc_header_t); */
+#define STOC_ENTRY 40 /* sizeof(fip_toc_entry_t); */
struct fipfile {
Chan *c;
@@ -20,25 +23,56 @@ struct fipfile {
long size[NR_FILES];
};
+struct fipuuid {
+ char time_low[4];
+ char time_mid[2];
+ char time_hi_and_version[2];
+ char clock_seq_hi_and_reserved;
+ char clock_seq_low;
+ char node[_UUID_NODE_LEN];
+};
+
+struct fipntry {
+ struct fipuuid uuid;
+ long long offset_address;
+ long long size;
+ long long flags;
+};
+
static struct fipfile archives[NR_FIPS];
static int nfips;
static int
-getntry(Chan *c, struct fip_toc_entry *ntry)
+getntry(Chan *c, struct fipntry *ntry)
{
- int n;
+ int i, n;
+ static unsigned char buf[STOC_ENTRY];
- // TODO: improve the way the entries are read in order to be more portable
- n = devtab[c->type]->read(c, ntry, sizeof(*ntry));
+ n = devtab[c->type]->read(c, buf, sizeof(buf));
if (n <= 0)
return n;
- if (n != sizeof(*ntry)) {
+ if (n != sizeof(buf)) {
errno = EINVAL;
return -1;
}
+ n = 0;
+ for (i = 0; i < 4; i++)
+ CHAR(ntry->uuid.time_low[i], buf, n, sizeof(buf));
+ for (i = 0; i < 2; i++)
+ CHAR(ntry->uuid.time_mid[i], buf, n, sizeof(buf));
+ for (i = 0; i < 2; i++)
+ CHAR(ntry->uuid.time_hi_and_version[i], buf, n, sizeof(buf));
+ CHAR(ntry->uuid.clock_seq_hi_and_reserved, buf, n, sizeof(buf));
+ CHAR(ntry->uuid.clock_seq_low, buf, n, sizeof(buf));
+ for (i = 0; i < _UUID_NODE_LEN; i++)
+ CHAR(ntry->uuid.node[i], buf, n, sizeof(buf));
+ LLONG(ntry->offset_address, buf, n, sizeof(buf));
+ LLONG(ntry->size, buf, n, sizeof(buf));
+ LLONG(ntry->flags, buf, n, sizeof(buf));
+
if (ntry->size > LONG_MAX || ntry->offset_address > LONG_MAX) {
errno = EINVAL;
return -1;
@@ -51,7 +85,7 @@ getntry(Chan *c, struct fip_toc_entry *ntry)
}
static int
-uuideq(const struct uuid *u1, const struct uuid *u2)
+uuideq(const struct fipuuid *u1, const struct fipuuid *u2)
{
if (u1->clock_seq_hi_and_reserved != u2->clock_seq_hi_and_reserved)
return 0;
@@ -74,13 +108,13 @@ fipgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
int i, r;
long off;
Chan nc;
- struct fip_toc_entry ntry;
+ struct fipntry ntry;
struct fipfile *fip;
static char unk[NAMELEN];
struct uuidnames {
const char name[NAMELEN];
- const struct uuid uuid;
+ const struct fipuuid uuid;
};
// TODO: generate this array from a text file
@@ -120,7 +154,7 @@ fipgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
clone(archives[c->dev].c, &nc);
fip = &archives[nc.dev];
- off = sizeof(struct fip_toc_header);
+ off = STOC_HEADER;
for (i = 0; i <= n; i++) {
if (fip->offset[i] == -1)
return 0;
@@ -203,10 +237,10 @@ static Chan *
fipmount(Chan *c, char *spec)
{
int r, n, t;
+ long name;
Chan *cspec;
- char buf[STOC_HEADER_NAME];
- struct fip_toc_entry ntry;
- struct fip_toc_header hdr;
+ unsigned char buf[STOC_HEADER_NAME];
+ struct fipntry ntry;
struct fipfile *fip;
if (nfips == NR_FIPS) {
@@ -222,17 +256,18 @@ fipmount(Chan *c, char *spec)
return NULL;
fip->c = cspec;
- // TODO: improve the way the header is read in order to be more portable
r = devtab[cspec->type]->read(cspec, buf, STOC_HEADER_NAME);
if (r < 0)
goto err;
- if (r != STOC_HEADER_NAME || *((uint32_t *)buf) != TOC_HEADER_NAME) {
+ n = 0;
+ LONG(name, buf, n, sizeof(buf));
+ if (r != STOC_HEADER_NAME || name != TOC_HEADER_NAME) {
errno = EINVAL;
goto err;
}
t = cspec->type;
- if (devtab[t]->seek(cspec, sizeof(hdr), KSEEK_SET) < 0)
+ if (devtab[t]->seek(cspec, STOC_HEADER, KSEEK_SET) < 0)
goto err;
for (n = 0; n < NR_FILES; n++) {
switch (getntry(cspec, &ntry)) {