commit d94a222d93f9786881c8b7e6e86f0ff3963b992e
parent eff6c097f55b7122e50ef1870f803511c509df16
Author: Ambroise Vincent <ambroise.vincent@arm.com>
Date: Thu, 18 Apr 2019 16:23:14 +0100
[dev] Add FIP filesystem
Change-Id: I9139562767d60adb6de6f16f9ae15c9700778c2e
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>
Diffstat:
8 files changed, 409 insertions(+), 4 deletions(-)
diff --git a/drivers/dev.h b/drivers/dev.h
@@ -1,9 +1,10 @@
#include <stddef.h>
-#define NR_CHANS 15
+#define NR_CHANS 20
#define NR_UARTS 2
#define NR_CONSS 1
#define NR_BINDS 4
+#define NR_FILES 20
#define NODEV 255
#define CHDIR (1 << 15)
diff --git a/drivers/devar.c b/drivers/devar.c
@@ -9,7 +9,6 @@
#include "dev.h"
#define NR_ARS 2
-#define NR_FILES 10
#define ARMAG "!<arch>\n" /* ar "magic number" */
#define SARMAG 8 /* strlen(ARMAG); */
@@ -57,7 +56,7 @@ gethdr(Chan *c, struct ar_hdr *hdr)
hdr->ar_name[i] = '\0';
}
- return 1;
+ return 1;
}
static int
@@ -124,7 +123,8 @@ arread(Chan *c, void *buf, int n)
return -1;
n = devtab[cs.type]->read(&cs, buf, n);
- c->offset += n;
+ if (n > 0)
+ c->offset += n;
return n;
}
diff --git a/drivers/devfip.c b/drivers/devfip.c
@@ -0,0 +1,242 @@
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rcode/rcode.h>
+#include <rcode/9p.h>
+
+#include "dev.h"
+#include "fip.h"
+
+#define NR_FIPS 2
+
+#define STOC_HEADER_NAME 4 /* strlen(TOC_HEADER_NAME); */
+
+struct fipfile {
+ Chan *c;
+ long offset[NR_FILES];
+ long size[NR_FILES];
+};
+
+static struct fipfile archives[NR_FIPS];
+static int nfips;
+
+static int
+getntry(Chan *c, struct fip_toc_entry *ntry)
+{
+ int n;
+
+ // TODO: improve the way the entries are read in order to be more portable
+ n = devtab[c->type]->read(c, ntry, sizeof(*ntry));
+ if (n <= 0)
+ return n;
+
+ if (n != sizeof(*ntry)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (ntry->size > LONG_MAX || ntry->offset_address > LONG_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (ntry->size == 0)
+ return 0;
+
+ return 1;
+}
+
+static int
+uuideq(const struct uuid *u1, const struct uuid *u2)
+{
+ if (u1->clock_seq_hi_and_reserved != u2->clock_seq_hi_and_reserved)
+ return 0;
+ if (u1->clock_seq_low != u2->clock_seq_low)
+ return 0;
+ if (memcmp(u1->node, u2->node, sizeof(u1->node)))
+ return 0;
+ if (memcmp(u1->time_hi_and_version, u2->time_hi_and_version, sizeof(u1->time_hi_and_version)))
+ return 0;
+ if (memcmp(u1->time_low, u2->time_low, sizeof(u1->time_low)))
+ return 0;
+ if (memcmp(u1->time_mid, u2->time_mid, sizeof(u1->time_mid)))
+ return 0;
+ return 1;
+}
+
+static int
+fipgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
+{
+ int i, r;
+ static char unk[NAMELEN];
+ Chan nc;
+ struct fip_toc_entry ntry;
+ struct fipfile *fip;
+
+ struct uuidnames {
+ const char name[NAMELEN];
+ const struct uuid uuid;
+ };
+
+ // TODO: generate this array from a text file
+ static const struct uuidnames uuidnames[] = {
+ {"scp-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U},
+ {"bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_BL2U},
+ {"ns-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U},
+ {"fwu.crt", UUID_TRUSTED_FWU_CERT},
+ {"bl2.bin", UUID_TRUSTED_BOOT_FIRMWARE_BL2},
+ {"scp-bl2.bin", UUID_SCP_FIRMWARE_SCP_BL2},
+ {"bl31.bin", UUID_EL3_RUNTIME_FIRMWARE_BL31},
+ {"bl32.bin", UUID_SECURE_PAYLOAD_BL32},
+ {"bl32-xtr1.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA1},
+ {"bl32-xtr2.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA2},
+ {"bl33.bin", UUID_NON_TRUSTED_FIRMWARE_BL33},
+ {"rot-k.crt", UUID_ROT_KEY_CERT},
+ {"trstd-k.crt", UUID_TRUSTED_KEY_CERT},
+ {"nt-k.crt", UUID_NON_TRUSTED_WORLD_KEY_CERT},
+ {"scp-fw-k.crt", UUID_SCP_FW_KEY_CERT},
+ {"soc-fw-k.crt", UUID_SOC_FW_KEY_CERT},
+ {"tos-fw-k.crt", UUID_TRUSTED_OS_FW_KEY_CERT},
+ {"nt-fw-k.crt", UUID_NON_TRUSTED_FW_KEY_CERT},
+ {"tb-fw.crt", UUID_TRUSTED_BOOT_FW_CERT},
+ {"scp-fw-c.crt", UUID_SCP_FW_CONTENT_CERT},
+ {"soc-fw-c.crt", UUID_SOC_FW_CONTENT_CERT},
+ {"tos-fw-c.crt", UUID_TRUSTED_OS_FW_CONTENT_CERT},
+ {"nt-fw-c.crt", UUID_NON_TRUSTED_FW_CONTENT_CERT},
+ {"hw.cfg", UUID_HW_CONFIG},
+ {"tb-fw.cfg", UUID_TB_FW_CONFIG},
+ {"soc-fw.cfg", UUID_SOC_FW_CONFIG},
+ {"tos-fw.cfg", UUID_TOS_FW_CONFIG},
+ {"nt-fw.cfg", UUID_NT_FW_CONFIG}
+ };
+
+ if (c->dev >= nfips)
+ panic("fipgen");
+ clone(archives[c->dev].c, &nc);
+ fip = &archives[nc.dev];
+
+ for (i = 0; i <= n; i++) {
+ if (fip->offset[i] == -1)
+ return 0;
+ if (devseek(&nc, sizeof(struct fip_toc_header) + i * sizeof(ntry), RSEEK_SET) < 0)
+ return -1;
+ if ((r = getntry(&nc, &ntry)) <= 0)
+ return r;
+ }
+
+ for (i = 0; i < NELEM(uuidnames); i++) {
+ if (uuideq(&uuidnames[i].uuid, &ntry.uuid))
+ break;
+ }
+
+ if (i < NELEM(uuidnames)) {
+ mkentry(c, dir, uuidnames[i].name, ntry.size, n, O_READ);
+ } else {
+ // TODO: set name depending on uuid node value
+ mkentry(c, dir, unk, ntry.size, n, O_READ);
+ }
+
+ return 1;
+}
+
+static int
+fipwalk(Chan *c, const char *name)
+{
+ return devwalk(c, name, NULL, 0, fipgen);
+}
+
+static int
+fipread(Chan *c, void *buf, int n)
+{
+ long off;
+ Chan cs;
+ struct fipfile *fip;
+
+ if (c->qid == CHDIR)
+ return dirread(c, buf, n, NULL, 0, fipgen);
+
+ if (c->dev >= nfips || (c->qid & CHDIR))
+ panic("fipread1");
+ fip = &archives[c->dev];
+
+ if (c->qid >= NR_FILES || fip->offset[c->qid] < 0)
+ panic("fipread2");
+ clone(fip->c, &cs);
+
+ if (c->offset >= fip->size[c->qid])
+ return 0;
+
+ off = fip->offset[c->qid] + c->offset;
+ if (devseek(&cs, off, RSEEK_SET) < 0)
+ return -1;
+
+ n = devtab[cs.type]->read(&cs, buf, n);
+ if (n > 0)
+ c->offset += n;
+
+ return n;
+}
+
+static Chan *
+fipmount(Chan *c, char *spec)
+{
+ int r, n;
+ Chan *cspec;
+ char buf[STOC_HEADER_NAME];
+ struct fip_toc_entry ntry;
+ struct fip_toc_header hdr;
+ struct fipfile *fip;
+
+ if (nfips == NR_FIPS) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ fip = &archives[nfips];
+
+ for (n = 0; n < NR_FILES; n++)
+ fip->offset[n] = -1;
+
+ if ((cspec = namec(spec, O_READ)) < 0)
+ 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) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ if (devseek(cspec, sizeof(hdr), RSEEK_SET) < 0)
+ goto err;
+ for (n = 0; n < NR_FILES; n++) {
+ switch (getntry(cspec, &ntry)) {
+ case 0:
+ return devattach('F', nfips++);
+ case -1:
+ goto err;
+ default:
+ fip->offset[n] = ntry.offset_address;
+ fip->size[n] = ntry.size;
+ break;
+ }
+ }
+ errno = ENOMEM;
+
+err:
+ chanclose(cspec);
+ return NULL;
+}
+
+const Dev fipdevtab = {
+ .id = 'F',
+ .walk = fipwalk,
+ .read = fipread,
+ .write = devwrite,
+ .mount = fipmount,
+};
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -14,6 +14,7 @@ enum Orootqid {
Qdevcons,
Qrealm,
Qarfs,
+ Qfip,
Qblobs,
Qblobctl,
};
@@ -27,6 +28,7 @@ static const Dirtab dirtab[] = {
{"realm", CHDIR | Qrealm, 0, O_READ},
{"blobs", CHDIR | Qblobs, 0, O_READ},
{"arfs", CHDIR | Qarfs, 0, O_READ},
+ {"fip", CHDIR | Qfip, 0, O_READ},
};
static const Dirtab devfstab[] = {
diff --git a/drivers/fip.h b/drivers/fip.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FIRMWARE_IMAGE_PACKAGE_H
+#define FIRMWARE_IMAGE_PACKAGE_H
+
+#include <stdint.h>
+
+#include "uuid.h"
+
+/* This is used as a signature to validate the blob header */
+#define TOC_HEADER_NAME 0xAA640001
+
+
+/* ToC Entry UUIDs */
+#define UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U \
+ {{0x65, 0x92, 0x27, 0x03}, {0x2f, 0x74}, {0xe6, 0x44}, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} }
+#define UUID_TRUSTED_UPDATE_FIRMWARE_BL2U \
+ {{0x60, 0xb3, 0xeb, 0x37}, {0xc1, 0xe5}, {0xea, 0x41}, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} }
+#define UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U \
+ {{0x4f, 0x51, 0x1d, 0x11}, {0x2b, 0xe5}, {0x4e, 0x49}, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} }
+#define UUID_TRUSTED_FWU_CERT \
+ {{0x71, 0x40, 0x8a, 0xb2}, {0x18, 0xd6}, {0x87, 0x4c}, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} }
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \
+ {{0x5f, 0xf9, 0xec, 0x0b}, {0x4d, 0x22}, {0x3e, 0x4d}, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} }
+#define UUID_SCP_FIRMWARE_SCP_BL2 \
+ {{0x97, 0x66, 0xfd, 0x3d}, {0x89, 0xbe}, {0xe8, 0x49}, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \
+ {{0x47, 0xd4, 0x08, 0x6d}, {0x4c, 0xfe}, {0x98, 0x46}, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} }
+#define UUID_SECURE_PAYLOAD_BL32 \
+ {{0x05, 0xd0, 0xe1, 0x89}, {0x53, 0xdc}, {0x13, 0x47}, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
+#define UUID_SECURE_PAYLOAD_BL32_EXTRA1 \
+ {{0x0b, 0x70, 0xc2, 0x9b}, {0x2a, 0x5a}, {0x78, 0x40}, 0x9f, 0x65, {0x0a, 0x56, 0x82, 0x73, 0x82, 0x88} }
+#define UUID_SECURE_PAYLOAD_BL32_EXTRA2 \
+ {{0x8e, 0xa8, 0x7b, 0xb1}, {0xcf, 0xa2}, {0x3f, 0x4d}, 0x85, 0xfd, {0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33 \
+ {{0xd6, 0xd0, 0xee, 0xa7}, {0xfc, 0xea}, {0xd5, 0x4b}, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+/* Key certificates */
+#define UUID_ROT_KEY_CERT \
+ {{0x86, 0x2d, 0x1d, 0x72}, {0xf8, 0x60}, {0xe4, 0x11}, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
+#define UUID_TRUSTED_KEY_CERT \
+ {{0x82, 0x7e, 0xe8, 0x90}, {0xf8, 0x60}, {0xe4, 0x11}, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
+#define UUID_NON_TRUSTED_WORLD_KEY_CERT \
+ {{0x1c, 0x67, 0x87, 0x3d}, {0x5f, 0x63}, {0xe4, 0x11}, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} }
+#define UUID_SCP_FW_KEY_CERT \
+ {{0x02, 0x42, 0x21, 0xa1}, {0xf8, 0x60}, {0xe4, 0x11}, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} }
+#define UUID_SOC_FW_KEY_CERT \
+ {{0x8a, 0xb8, 0xbe, 0xcc}, {0xf9, 0x60}, {0xe4, 0x11}, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} }
+#define UUID_TRUSTED_OS_FW_KEY_CERT \
+ {{0x94, 0x77, 0xd6, 0x03}, {0xfb, 0x60}, {0xe4, 0x11}, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} }
+#define UUID_NON_TRUSTED_FW_KEY_CERT \
+ {{0x8a, 0xd5, 0x83, 0x2a}, {0xfb, 0x60}, {0xe4, 0x11}, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} }
+/* Content certificates */
+#define UUID_TRUSTED_BOOT_FW_CERT \
+ {{0xd6, 0xe2, 0x69, 0xea}, {0x5d, 0x63}, {0xe4, 0x11}, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} }
+#define UUID_SCP_FW_CONTENT_CERT \
+ {{0x44, 0xbe, 0x6f, 0x04}, {0x5e, 0x63}, {0xe4, 0x11}, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} }
+#define UUID_SOC_FW_CONTENT_CERT \
+ {{0xe2, 0xb2, 0x0c, 0x20}, {0x5e, 0x63}, {0xe4, 0x11}, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} }
+#define UUID_TRUSTED_OS_FW_CONTENT_CERT \
+ {{0xa4, 0x9f, 0x44, 0x11}, {0x5e, 0x63}, {0xe4, 0x11}, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} }
+#define UUID_NON_TRUSTED_FW_CONTENT_CERT \
+ {{0x8e, 0xc4, 0xc1, 0xf3}, {0x5d, 0x63}, {0xe4, 0x11}, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} }
+/* Dynamic configs */
+#define UUID_HW_CONFIG \
+ {{0x08, 0xb8, 0xf1, 0xd9}, {0xc9, 0xcf}, {0x93, 0x49}, 0xa9, 0x62, {0x6f, 0xbc, 0x6b, 0x72, 0x65, 0xcc} }
+#define UUID_TB_FW_CONFIG \
+ {{0x6c, 0x04, 0x58, 0xff}, {0xaf, 0x6b}, {0x7d, 0x4f}, 0x82, 0xed, {0xaa, 0x27, 0xbc, 0x69, 0xbf, 0xd2} }
+#define UUID_SOC_FW_CONFIG \
+ {{0x99, 0x79, 0x81, 0x4b}, {0x03, 0x76}, {0xfb, 0x46}, 0x8c, 0x8e, {0x8d, 0x26, 0x7f, 0x78, 0x59, 0xe0} }
+#define UUID_TOS_FW_CONFIG \
+ {{0x26, 0x25, 0x7c, 0x1a}, {0xdb, 0xc6}, {0x7f, 0x47}, 0x8d, 0x96, {0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21} }
+#define UUID_NT_FW_CONFIG \
+ {{0x28, 0xda, 0x98, 0x15}, {0x93, 0xe8}, {0x7e, 0x44}, 0xac, 0x66, {0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9} }
+
+typedef struct fip_toc_header {
+ uint32_t name;
+ uint32_t serial_number;
+ uint64_t flags;
+} fip_toc_header_t;
+
+typedef struct fip_toc_entry {
+ uuid_t uuid;
+ uint64_t offset_address;
+ uint64_t size;
+ uint64_t flags;
+} fip_toc_entry_t;
+
+#endif /* FIRMWARE_IMAGE_PACKAGE_H */
diff --git a/drivers/uuid.h b/drivers/uuid.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef UUID_H
+#define UUID_H
+
+/* Length of a node address (an IEEE 802 address). */
+#define _UUID_NODE_LEN 6
+
+/* Length of UUID string including dashes. */
+#define _UUID_STR_LEN 36
+
+/*
+ * See also:
+ * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * A DCE 1.1 compatible source representation of UUIDs.
+ */
+struct uuid {
+ uint8_t time_low[4];
+ uint8_t time_mid[2];
+ uint8_t time_hi_and_version[2];
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[_UUID_NODE_LEN];
+};
+
+/* XXX namespace pollution? */
+typedef struct uuid uuid_t;
+
+#endif /* UUID_H */
diff --git a/target/native/rcode b/target/native/rcode
@@ -4,4 +4,7 @@ dev
pl011 base=0x1C090000,clk=24000000,rate=115200
pl011 base=0x1c0c0000,clk=24000000,rate=115200
cons
+ fip
+blob
+ fip.bin 0x1000,0x100000
end
diff --git a/target/native/rom.c b/target/native/rom.c
@@ -131,6 +131,9 @@ namespace(void)
// Link required after bind
conslink((Attr []) {{"in", "/dev/uart0/raw"},{"out", "/dev/uart0/raw"},{0}});
+ if (mount("#F", "/fip", "/blobs/fip.bin") < 0)
+ goto error;
+
return;
error: