1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019-2021, Arm Limited. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <lib/debugfs.h> 9*91f16700Schasinglulu #include <limits.h> 10*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 11*91f16700Schasinglulu #include <stdlib.h> 12*91f16700Schasinglulu #include <string.h> 13*91f16700Schasinglulu #include <tools_share/firmware_image_package.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include "dev.h" 16*91f16700Schasinglulu 17*91f16700Schasinglulu #define NR_FIPS 1 18*91f16700Schasinglulu #define STOC_HEADER (sizeof(fip_toc_header_t)) 19*91f16700Schasinglulu #define STOC_ENTRY (sizeof(fip_toc_entry_t)) 20*91f16700Schasinglulu 21*91f16700Schasinglulu struct fipfile { 22*91f16700Schasinglulu chan_t *c; 23*91f16700Schasinglulu long offset[NR_FILES]; 24*91f16700Schasinglulu long size[NR_FILES]; 25*91f16700Schasinglulu }; 26*91f16700Schasinglulu 27*91f16700Schasinglulu struct fip_entry { 28*91f16700Schasinglulu uuid_t uuid; 29*91f16700Schasinglulu long long offset_address; 30*91f16700Schasinglulu long long size; 31*91f16700Schasinglulu long long flags; 32*91f16700Schasinglulu }; 33*91f16700Schasinglulu 34*91f16700Schasinglulu struct uuidnames { 35*91f16700Schasinglulu const char name[NAMELEN]; 36*91f16700Schasinglulu const uuid_t uuid; 37*91f16700Schasinglulu }; 38*91f16700Schasinglulu 39*91f16700Schasinglulu /******************************************************************************* 40*91f16700Schasinglulu * This array links the FIP file names to their UUID. 41*91f16700Schasinglulu * The elements are ordered according to the image number stored in 42*91f16700Schasinglulu * tbbr_img_def.h, starting at index 1. 43*91f16700Schasinglulu * 44*91f16700Schasinglulu * TODO: this name to uuid binding will preferably be done using 45*91f16700Schasinglulu * the coming Property Access Layer / Firmware CONFiguration feature. 46*91f16700Schasinglulu ******************************************************************************/ 47*91f16700Schasinglulu static const struct uuidnames uuidnames[] = { 48*91f16700Schasinglulu {"", { {0}, {0}, {0}, 0, 0, {0} } }, 49*91f16700Schasinglulu {"bl2.bin", UUID_TRUSTED_BOOT_FIRMWARE_BL2}, 50*91f16700Schasinglulu {"scp-bl2.bin", UUID_SCP_FIRMWARE_SCP_BL2}, 51*91f16700Schasinglulu {"bl31.bin", UUID_EL3_RUNTIME_FIRMWARE_BL31}, 52*91f16700Schasinglulu {"bl32.bin", UUID_SECURE_PAYLOAD_BL32}, 53*91f16700Schasinglulu {"bl33.bin", UUID_NON_TRUSTED_FIRMWARE_BL33}, 54*91f16700Schasinglulu {"tb-fw.crt", UUID_TRUSTED_BOOT_FW_CERT}, 55*91f16700Schasinglulu {"trstd-k.crt", UUID_TRUSTED_KEY_CERT}, 56*91f16700Schasinglulu {"scp-fw-k.crt", UUID_SCP_FW_KEY_CERT}, 57*91f16700Schasinglulu {"soc-fw-k.crt", UUID_SOC_FW_KEY_CERT}, 58*91f16700Schasinglulu {"tos-fw-k.crt", UUID_TRUSTED_OS_FW_KEY_CERT}, 59*91f16700Schasinglulu {"nt-fw-k.crt", UUID_NON_TRUSTED_FW_KEY_CERT}, 60*91f16700Schasinglulu {"scp-fw-c.crt", UUID_SCP_FW_CONTENT_CERT}, 61*91f16700Schasinglulu {"soc-fw-c.crt", UUID_SOC_FW_CONTENT_CERT}, 62*91f16700Schasinglulu {"tos-fw-c.crt", UUID_TRUSTED_OS_FW_CONTENT_CERT}, 63*91f16700Schasinglulu {"nt-fw-c.crt", UUID_NON_TRUSTED_FW_CONTENT_CERT}, 64*91f16700Schasinglulu { }, 65*91f16700Schasinglulu {"fwu.crt", UUID_TRUSTED_FWU_CERT}, 66*91f16700Schasinglulu {"scp-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U}, 67*91f16700Schasinglulu {"bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_BL2U}, 68*91f16700Schasinglulu {"ns-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U}, 69*91f16700Schasinglulu {"bl32-xtr1.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA1}, 70*91f16700Schasinglulu {"bl32-xtr2.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA2}, 71*91f16700Schasinglulu {"hw.cfg", UUID_HW_CONFIG}, 72*91f16700Schasinglulu {"tb-fw.cfg", UUID_TB_FW_CONFIG}, 73*91f16700Schasinglulu {"soc-fw.cfg", UUID_SOC_FW_CONFIG}, 74*91f16700Schasinglulu {"tos-fw.cfg", UUID_TOS_FW_CONFIG}, 75*91f16700Schasinglulu {"nt-fw.cfg", UUID_NT_FW_CONFIG}, 76*91f16700Schasinglulu {"fw.cfg", UUID_FW_CONFIG}, 77*91f16700Schasinglulu {"rot-k.crt", UUID_ROT_KEY_CERT}, 78*91f16700Schasinglulu {"nt-k.crt", UUID_NON_TRUSTED_WORLD_KEY_CERT}, 79*91f16700Schasinglulu {"sip-sp.crt", UUID_SIP_SECURE_PARTITION_CONTENT_CERT}, 80*91f16700Schasinglulu {"plat-sp.crt", UUID_PLAT_SECURE_PARTITION_CONTENT_CERT} 81*91f16700Schasinglulu }; 82*91f16700Schasinglulu 83*91f16700Schasinglulu /******************************************************************************* 84*91f16700Schasinglulu * This array contains all the available FIP files. 85*91f16700Schasinglulu ******************************************************************************/ 86*91f16700Schasinglulu static struct fipfile archives[NR_FIPS]; 87*91f16700Schasinglulu 88*91f16700Schasinglulu /******************************************************************************* 89*91f16700Schasinglulu * This variable stores the current number of registered FIP files. 90*91f16700Schasinglulu ******************************************************************************/ 91*91f16700Schasinglulu static int nfips; 92*91f16700Schasinglulu 93*91f16700Schasinglulu /******************************************************************************* 94*91f16700Schasinglulu * This function parses the ToC of the FIP. 95*91f16700Schasinglulu ******************************************************************************/ 96*91f16700Schasinglulu static int get_entry(chan_t *c, struct fip_entry *entry) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu int n; 99*91f16700Schasinglulu 100*91f16700Schasinglulu n = devtab[c->index]->read(c, entry, sizeof(struct fip_entry)); 101*91f16700Schasinglulu if (n <= 0) { 102*91f16700Schasinglulu return n; 103*91f16700Schasinglulu } 104*91f16700Schasinglulu 105*91f16700Schasinglulu if (n != sizeof(struct fip_entry)) { 106*91f16700Schasinglulu return -1; 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu if (entry->size == 0) { 110*91f16700Schasinglulu return 0; 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu return 1; 114*91f16700Schasinglulu } 115*91f16700Schasinglulu 116*91f16700Schasinglulu /******************************************************************************* 117*91f16700Schasinglulu * This function exposes the FIP images as files. 118*91f16700Schasinglulu ******************************************************************************/ 119*91f16700Schasinglulu static int fipgen(chan_t *c, const dirtab_t *tab, int ntab, int n, dir_t *dir) 120*91f16700Schasinglulu { 121*91f16700Schasinglulu int i, r; 122*91f16700Schasinglulu long off; 123*91f16700Schasinglulu chan_t nc; 124*91f16700Schasinglulu struct fip_entry entry; 125*91f16700Schasinglulu struct fipfile *fip; 126*91f16700Schasinglulu static const char unk[] = "unknown"; 127*91f16700Schasinglulu 128*91f16700Schasinglulu if (c->dev >= nfips) { 129*91f16700Schasinglulu panic(); 130*91f16700Schasinglulu } 131*91f16700Schasinglulu 132*91f16700Schasinglulu if (clone(archives[c->dev].c, &nc) == NULL) { 133*91f16700Schasinglulu panic(); 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu fip = &archives[nc.dev]; 137*91f16700Schasinglulu 138*91f16700Schasinglulu off = STOC_HEADER; 139*91f16700Schasinglulu for (i = 0; i <= n; i++) { 140*91f16700Schasinglulu if (fip->offset[i] == -1) { 141*91f16700Schasinglulu return 0; 142*91f16700Schasinglulu } 143*91f16700Schasinglulu 144*91f16700Schasinglulu if (devtab[nc.index]->seek(&nc, off, KSEEK_SET) < 0) { 145*91f16700Schasinglulu return -1; 146*91f16700Schasinglulu } 147*91f16700Schasinglulu 148*91f16700Schasinglulu r = get_entry(&nc, &entry); 149*91f16700Schasinglulu if (r <= 0) { 150*91f16700Schasinglulu return r; 151*91f16700Schasinglulu } 152*91f16700Schasinglulu 153*91f16700Schasinglulu off += sizeof(entry); 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu for (i = 1; i < NELEM(uuidnames); i++) { 157*91f16700Schasinglulu if (memcmp(&uuidnames[i].uuid, 158*91f16700Schasinglulu &entry.uuid, sizeof(uuid_t)) == 0) { 159*91f16700Schasinglulu break; 160*91f16700Schasinglulu } 161*91f16700Schasinglulu } 162*91f16700Schasinglulu 163*91f16700Schasinglulu if (i < NELEM(uuidnames)) { 164*91f16700Schasinglulu make_dir_entry(c, dir, uuidnames[i].name, 165*91f16700Schasinglulu entry.size, n, O_READ); 166*91f16700Schasinglulu } else { 167*91f16700Schasinglulu // TODO: set name depending on uuid node value 168*91f16700Schasinglulu make_dir_entry(c, dir, unk, entry.size, n, O_READ); 169*91f16700Schasinglulu } 170*91f16700Schasinglulu 171*91f16700Schasinglulu return 1; 172*91f16700Schasinglulu } 173*91f16700Schasinglulu 174*91f16700Schasinglulu static int fipwalk(chan_t *c, const char *name) 175*91f16700Schasinglulu { 176*91f16700Schasinglulu return devwalk(c, name, NULL, 0, fipgen); 177*91f16700Schasinglulu } 178*91f16700Schasinglulu 179*91f16700Schasinglulu static int fipstat(chan_t *c, const char *file, dir_t *dir) 180*91f16700Schasinglulu { 181*91f16700Schasinglulu return devstat(c, file, dir, NULL, 0, fipgen); 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu /******************************************************************************* 185*91f16700Schasinglulu * This function copies at most n bytes of the FIP image referred by c into 186*91f16700Schasinglulu * buf. 187*91f16700Schasinglulu ******************************************************************************/ 188*91f16700Schasinglulu static int fipread(chan_t *c, void *buf, int n) 189*91f16700Schasinglulu { 190*91f16700Schasinglulu long off; 191*91f16700Schasinglulu chan_t cs; 192*91f16700Schasinglulu struct fipfile *fip; 193*91f16700Schasinglulu long size; 194*91f16700Schasinglulu 195*91f16700Schasinglulu /* Only makes sense when using debug language */ 196*91f16700Schasinglulu assert(c->qid != CHDIR); 197*91f16700Schasinglulu 198*91f16700Schasinglulu if ((c->dev >= nfips) || ((c->qid & CHDIR) != 0)) { 199*91f16700Schasinglulu panic(); 200*91f16700Schasinglulu } 201*91f16700Schasinglulu 202*91f16700Schasinglulu fip = &archives[c->dev]; 203*91f16700Schasinglulu 204*91f16700Schasinglulu if ((c->qid >= NR_FILES) || (fip->offset[c->qid] < 0)) { 205*91f16700Schasinglulu panic(); 206*91f16700Schasinglulu } 207*91f16700Schasinglulu 208*91f16700Schasinglulu if (clone(fip->c, &cs) == NULL) { 209*91f16700Schasinglulu panic(); 210*91f16700Schasinglulu } 211*91f16700Schasinglulu 212*91f16700Schasinglulu size = fip->size[c->qid]; 213*91f16700Schasinglulu if (c->offset >= size) { 214*91f16700Schasinglulu return 0; 215*91f16700Schasinglulu } 216*91f16700Schasinglulu 217*91f16700Schasinglulu if (n < 0) { 218*91f16700Schasinglulu return -1; 219*91f16700Schasinglulu } 220*91f16700Schasinglulu 221*91f16700Schasinglulu if (n > (size - c->offset)) { 222*91f16700Schasinglulu n = size - c->offset; 223*91f16700Schasinglulu } 224*91f16700Schasinglulu 225*91f16700Schasinglulu off = fip->offset[c->qid] + c->offset; 226*91f16700Schasinglulu if (devtab[cs.index]->seek(&cs, off, KSEEK_SET) < 0) { 227*91f16700Schasinglulu return -1; 228*91f16700Schasinglulu } 229*91f16700Schasinglulu 230*91f16700Schasinglulu n = devtab[cs.index]->read(&cs, buf, n); 231*91f16700Schasinglulu if (n > 0) { 232*91f16700Schasinglulu c->offset += n; 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu return n; 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu /******************************************************************************* 239*91f16700Schasinglulu * This function parses the FIP spec and registers its images in order to 240*91f16700Schasinglulu * expose them as files in the driver namespace. 241*91f16700Schasinglulu * It acts as an initialization function for the FIP driver. 242*91f16700Schasinglulu * It returns a pointer to the newly created channel. 243*91f16700Schasinglulu ******************************************************************************/ 244*91f16700Schasinglulu static chan_t *fipmount(chan_t *c, const char *spec) 245*91f16700Schasinglulu { 246*91f16700Schasinglulu int r, n, t; 247*91f16700Schasinglulu chan_t *cspec; 248*91f16700Schasinglulu uint32_t hname; 249*91f16700Schasinglulu struct fip_entry entry; 250*91f16700Schasinglulu struct fipfile *fip; 251*91f16700Schasinglulu dir_t dir; 252*91f16700Schasinglulu 253*91f16700Schasinglulu if (nfips == NR_FIPS) { 254*91f16700Schasinglulu return NULL; 255*91f16700Schasinglulu } 256*91f16700Schasinglulu 257*91f16700Schasinglulu fip = &archives[nfips]; 258*91f16700Schasinglulu 259*91f16700Schasinglulu for (n = 0; n < NR_FILES; n++) { 260*91f16700Schasinglulu fip->offset[n] = -1; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu 263*91f16700Schasinglulu cspec = path_to_channel(spec, O_READ); 264*91f16700Schasinglulu if (cspec == NULL) { 265*91f16700Schasinglulu return NULL; 266*91f16700Schasinglulu } 267*91f16700Schasinglulu 268*91f16700Schasinglulu fip->c = cspec; 269*91f16700Schasinglulu 270*91f16700Schasinglulu r = devtab[cspec->index]->read(cspec, &hname, sizeof(hname)); 271*91f16700Schasinglulu if (r < 0) { 272*91f16700Schasinglulu goto err; 273*91f16700Schasinglulu } 274*91f16700Schasinglulu 275*91f16700Schasinglulu if ((r != sizeof(hname)) || (hname != TOC_HEADER_NAME)) { 276*91f16700Schasinglulu goto err; 277*91f16700Schasinglulu } 278*91f16700Schasinglulu 279*91f16700Schasinglulu if (stat(spec, &dir) < 0) { 280*91f16700Schasinglulu goto err; 281*91f16700Schasinglulu } 282*91f16700Schasinglulu 283*91f16700Schasinglulu t = cspec->index; 284*91f16700Schasinglulu if (devtab[t]->seek(cspec, STOC_HEADER, KSEEK_SET) < 0) { 285*91f16700Schasinglulu goto err; 286*91f16700Schasinglulu } 287*91f16700Schasinglulu 288*91f16700Schasinglulu for (n = 0; n < NR_FILES; n++) { 289*91f16700Schasinglulu switch (get_entry(cspec, &entry)) { 290*91f16700Schasinglulu case 0: 291*91f16700Schasinglulu return attach('F', nfips++); 292*91f16700Schasinglulu case -1: 293*91f16700Schasinglulu goto err; 294*91f16700Schasinglulu default: 295*91f16700Schasinglulu if ((entry.offset_address + entry.size) > dir.length) { 296*91f16700Schasinglulu goto err; 297*91f16700Schasinglulu } 298*91f16700Schasinglulu 299*91f16700Schasinglulu fip->offset[n] = entry.offset_address; 300*91f16700Schasinglulu fip->size[n] = entry.size; 301*91f16700Schasinglulu break; 302*91f16700Schasinglulu } 303*91f16700Schasinglulu } 304*91f16700Schasinglulu 305*91f16700Schasinglulu err: 306*91f16700Schasinglulu channel_close(cspec); 307*91f16700Schasinglulu return NULL; 308*91f16700Schasinglulu } 309*91f16700Schasinglulu 310*91f16700Schasinglulu const dev_t fipdevtab = { 311*91f16700Schasinglulu .id = 'F', 312*91f16700Schasinglulu .stat = fipstat, 313*91f16700Schasinglulu .clone = devclone, 314*91f16700Schasinglulu .attach = devattach, 315*91f16700Schasinglulu .walk = fipwalk, 316*91f16700Schasinglulu .read = fipread, 317*91f16700Schasinglulu .write = deverrwrite, 318*91f16700Schasinglulu .mount = fipmount, 319*91f16700Schasinglulu .seek = devseek 320*91f16700Schasinglulu }; 321*91f16700Schasinglulu 322