LCOV - code coverage report
Current view: top level - external/ffspart - ffspart.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 135 295 45.8 %
Date: 2024-09-10 18:37:41 Functions: 4 6 66.7 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Assemble a FFS Image (no, not that FFS, this FFS)
       4                 :            :  *
       5                 :            :  * Copyright 2013-2019 IBM Corp.
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <ctype.h>
       9                 :            : #include <errno.h>
      10                 :            : #include <fcntl.h>
      11                 :            : #include <getopt.h>
      12                 :            : #include <limits.h>
      13                 :            : #include <stdio.h>
      14                 :            : #include <stdlib.h>
      15                 :            : #include <string.h>
      16                 :            : #include <stdint.h>
      17                 :            : #include <stdbool.h>
      18                 :            : #include <sys/stat.h>
      19                 :            : #include <sys/mman.h>
      20                 :            : #include <unistd.h>
      21                 :            : 
      22                 :            : #include <libflash/libflash.h>
      23                 :            : #include <libflash/libffs.h>
      24                 :            : #include <libflash/blocklevel.h>
      25                 :            : #include <libflash/ecc.h>
      26                 :            : #include <common/arch_flash.h>
      27                 :            : 
      28                 :            : /*
      29                 :            :  * Flags:
      30                 :            :  *  - E: ECC for this part
      31                 :            :  */
      32                 :            : 
      33                 :            : /*
      34                 :            :  * TODO FIXME
      35                 :            :  * Max line theoretical max size:
      36                 :            :  *  - name: 15 chars = 15
      37                 :            :  *  - base: 0xffffffff = 10
      38                 :            :  *  - size: 0xffffffff = 10
      39                 :            :  *  - flag: E = 1
      40                 :            :  *
      41                 :            :  *  36 + 3 separators = 39
      42                 :            :  *  Plus \n 40
      43                 :            :  *  Lets do 50.
      44                 :            :  */
      45                 :            : #define MAX_LINE (PATH_MAX+255)
      46                 :            : #define MAX_TOCS 10
      47                 :            : #define SEPARATOR ','
      48                 :            : 
      49                 :            : /* Full version number (possibly includes gitid). */
      50                 :            : extern const char version[];
      51                 :            : 
      52                 :         56 : static int read_u32(const char *input, uint32_t *val)
      53                 :            : {
      54                 :         56 :         char *endptr;
      55                 :         56 :         *val = strtoul(input, &endptr, 0);
      56                 :         56 :         return (*endptr == SEPARATOR) ? 0 : 1;
      57                 :            : }
      58                 :            : 
      59                 :        168 : static const char *advance_line(const char *input)
      60                 :            : {
      61                 :        168 :         char *pos = strchr(input, SEPARATOR);
      62                 :        168 :         if (!pos)
      63                 :            :                 return NULL;
      64                 :        168 :         return pos + 1;
      65                 :            : }
      66                 :            : 
      67                 :          0 : static struct ffs_hdr *parse_toc(const char *line, uint32_t block_size,
      68                 :            :                 uint32_t block_count)
      69                 :            : {
      70                 :          0 :         struct ffs_entry_user user;
      71                 :          0 :         struct ffs_entry *ent;
      72                 :          0 :         struct ffs_hdr *hdr;
      73                 :          0 :         uint32_t tbase;
      74                 :          0 :         int rc;
      75                 :            : 
      76                 :          0 :         if (read_u32(line, &tbase)) {
      77                 :          0 :                 fprintf(stderr, "Couldn't parse TOC base address\n");
      78                 :          0 :                 return NULL;
      79                 :            :         }
      80                 :            : 
      81                 :          0 :         line = advance_line(line);
      82                 :          0 :         if (!line) {
      83                 :          0 :                 fprintf(stderr, "Couldn't find TOC flags\n");
      84                 :          0 :                 return NULL;
      85                 :            :         }
      86                 :            : 
      87                 :          0 :         rc = ffs_string_to_entry_user(line, strlen(line), &user);
      88                 :          0 :         if (rc) {
      89                 :          0 :                 fprintf(stderr, "Couldn't parse TOC flags\n");
      90                 :          0 :                 return NULL;
      91                 :            :         }
      92                 :            : 
      93                 :          0 :         rc = ffs_entry_new("part", tbase, 0, &ent);
      94                 :          0 :         if (rc) {
      95                 :          0 :                 fprintf(stderr, "Couldn't make entry for TOC@0x%08x\n", tbase);
      96                 :          0 :                 return NULL;
      97                 :            :         }
      98                 :            : 
      99                 :          0 :         rc = ffs_entry_user_set(ent, &user);
     100                 :          0 :         if (rc) {
     101                 :          0 :                 fprintf(stderr, "Invalid TOC flag\n");
     102                 :          0 :                 ffs_entry_put(ent);
     103                 :          0 :                 return NULL;
     104                 :            :         }
     105                 :            : 
     106                 :          0 :         rc = ffs_hdr_new(block_size, block_count, &ent, &hdr);
     107                 :          0 :         if (rc) {
     108                 :          0 :                 hdr = NULL;
     109                 :          0 :                 fprintf(stderr, "Couldn't make header for TOC@0x%08x\n", tbase);
     110                 :            :         }
     111                 :            : 
     112                 :          0 :         ffs_entry_put(ent);
     113                 :          0 :         return hdr;
     114                 :            : }
     115                 :            : 
     116                 :         28 : static int parse_entry(struct blocklevel_device *bl,
     117                 :            :                 struct ffs_hdr **tocs, const char *line, bool allow_empty)
     118                 :            : {
     119                 :         28 :         char name[FFS_PART_NAME_MAX + 2] = { 0 };
     120                 :         28 :         struct ffs_entry_user user = { 0 };
     121                 :         28 :         uint32_t pbase, psize, pactual, i;
     122                 :         28 :         struct ffs_entry *new_entry;
     123                 :         28 :         struct stat data_stat;
     124                 :         28 :         const char *filename;
     125                 :         28 :         bool added = false;
     126                 :         28 :         uint8_t *data_ptr, ecc = 0;
     127                 :         28 :         int data_fd, rc;
     128                 :         28 :         char *pos;
     129                 :            : 
     130                 :         28 :         memcpy(name, line, FFS_PART_NAME_MAX + 1);
     131                 :         28 :         pos = strchr(name, SEPARATOR);
     132                 :            :         /* There is discussion to be had as to if we should bail here */
     133                 :         28 :         if (!pos) {
     134                 :          0 :                 fprintf(stderr, "WARNING: Long partition name will get truncated to '%s'\n",
     135                 :            :                                 name);
     136                 :          0 :                 name[FFS_PART_NAME_MAX] = '\0';
     137                 :            :         } else {
     138                 :         28 :                 *pos = '\0';
     139                 :            :         }
     140                 :            : 
     141                 :         28 :         line = advance_line(line);
     142                 :         28 :         if (!line || read_u32(line, &pbase)) {
     143                 :          0 :                 fprintf(stderr, "Couldn't parse '%s' partition base address\n",
     144                 :            :                                 name);
     145                 :          0 :                 return -1;
     146                 :            :         }
     147                 :            : 
     148                 :         28 :         line = advance_line(line);
     149                 :         28 :         if (!line || read_u32(line, &psize)) {
     150                 :          0 :                 fprintf(stderr, "Couldn't parse '%s' partition length\n",
     151                 :            :                                 name);
     152                 :          0 :                 return -1;
     153                 :            :         }
     154                 :            : 
     155                 :         28 :         line = advance_line(line);
     156                 :         28 :         if (!line || !advance_line(line)) {
     157                 :          0 :                 fprintf(stderr, "Couldn't find '%s' partition flags\n",
     158                 :            :                                 name);
     159                 :          0 :                 return -1;
     160                 :            :         }
     161                 :            : 
     162                 :         28 :         rc = ffs_string_to_entry_user(line, advance_line(line) - 1 - line, &user);
     163                 :         28 :         if (rc) {
     164                 :          0 :                 fprintf(stderr, "Couldn't parse '%s' partition flags\n",
     165                 :            :                                 name);
     166                 :          0 :                 return -1;
     167                 :            :         }
     168                 :         28 :         line = advance_line(line);
     169                 :            :         /* Already checked return value */
     170                 :            : 
     171                 :         28 :         rc = ffs_entry_new(name, pbase, psize, &new_entry);
     172                 :         28 :         if (rc) {
     173                 :          0 :                 fprintf(stderr, "Invalid entry '%s' 0x%08x for 0x%08x\n",
     174                 :            :                                 name, pbase, psize);
     175                 :          0 :                 return -1;
     176                 :            :         }
     177                 :            : 
     178                 :         28 :         rc = ffs_entry_user_set(new_entry, &user);
     179                 :         28 :         if (rc) {
     180                 :          0 :                 fprintf(stderr, "Couldn't set '%s' partition flags\n",
     181                 :            :                                 name);
     182                 :          0 :                 ffs_entry_put(new_entry);
     183                 :          0 :                 return -1;
     184                 :            :         }
     185                 :            : 
     186                 :         28 :         if (has_flag(new_entry, FFS_MISCFLAGS_BACKUP)) {
     187                 :          1 :                 rc = ffs_entry_set_act_size(new_entry, 0);
     188                 :          1 :                 if (rc) {
     189                 :          0 :                         fprintf(stderr, "Couldn't set '%s' partition actual size\n",
     190                 :            :                                         name);
     191                 :          0 :                         ffs_entry_put(new_entry);
     192                 :          0 :                         return -1;
     193                 :            :                 }
     194                 :            :         }
     195                 :            : 
     196                 :         28 :         if (!advance_line(line)) {
     197                 :          0 :                 fprintf(stderr, "Missing TOC field for '%s' partition\n",
     198                 :            :                                 name);
     199                 :          0 :                 ffs_entry_put(new_entry);
     200                 :          0 :                 return -1;
     201                 :            :         }
     202                 :            : 
     203                 :         28 :         while (*line != SEPARATOR) {
     204                 :          0 :                 int toc = *(line++);
     205                 :            : 
     206                 :          0 :                 if (!isdigit(toc)) {
     207                 :          0 :                         fprintf(stderr, "Bad TOC value %d (%c) for '%s' partition\n",
     208                 :            :                                         toc, toc, name);
     209                 :          0 :                         ffs_entry_put(new_entry);
     210                 :          0 :                         return -1;
     211                 :            :                 }
     212                 :          0 :                 toc -= '0';
     213                 :          0 :                 if (!tocs[toc]) {
     214                 :          0 :                         fprintf(stderr, "No TOC with ID %d for '%s' partition\n",
     215                 :            :                                         toc, name);
     216                 :          0 :                         ffs_entry_put(new_entry);
     217                 :          0 :                         return -1;
     218                 :            :                 }
     219                 :          0 :                 rc = ffs_entry_add(tocs[toc], new_entry);
     220                 :          0 :                 if (rc) {
     221                 :          0 :                         fprintf(stderr, "Couldn't add '%s' partition to TOC %d: %d\n",
     222                 :            :                                         name, toc, rc);
     223                 :          0 :                         ffs_entry_put(new_entry);
     224                 :          0 :                         return rc;
     225                 :            :                 }
     226                 :            :                 added = true;
     227                 :            :         }
     228                 :         28 :         if (!added) {
     229                 :            :                 /*
     230                 :            :                  * They didn't specify a TOC in the TOC field, use
     231                 :            :                  * TOC@0 as the default
     232                 :            :                  */
     233                 :         28 :                 rc = ffs_entry_add(tocs[0], new_entry);
     234                 :         28 :                 if (rc) {
     235                 :          0 :                         fprintf(stderr, "Couldn't add '%s' partition to default TOC: %d\n",
     236                 :            :                                         name, rc);
     237                 :          0 :                         ffs_entry_put(new_entry);
     238                 :          0 :                         return rc;
     239                 :            :                 }
     240                 :            :         }
     241                 :         28 :         ffs_entry_put(new_entry);
     242                 :            : 
     243                 :         56 :         if (*line != '\0' && *(line + 1) != '\0') {
     244                 :         28 :                 size_t data_len;
     245                 :            : 
     246                 :         28 :                 filename = line + 1;
     247                 :            : 
     248                 :            :                 /*
     249                 :            :                  * Support flashing already ecc'd data as this is the case
     250                 :            :                  * for POWER8 SBE image binary.
     251                 :            :                  */
     252                 :         28 :                 if (has_ecc(new_entry) && !strstr(filename, ".ecc"))
     253                 :         20 :                         blocklevel_ecc_protect(bl, pbase, psize);
     254                 :            : 
     255                 :         28 :                 data_fd = open(filename, O_RDONLY);
     256                 :         28 :                 if (data_fd == -1) {
     257                 :          0 :                         fprintf(stderr, "Couldn't open file '%s' for '%s' partition "
     258                 :            :                                         "(%m)\n", filename, name);
     259                 :          0 :                         return -1;
     260                 :            :                 }
     261                 :            : 
     262                 :         28 :                 if (fstat(data_fd, &data_stat) == -1) {
     263                 :          0 :                         fprintf(stderr, "Couldn't stat file '%s' for '%s' partition "
     264                 :            :                                 "(%m)\n", filename, name);
     265                 :          0 :                         close(data_fd);
     266                 :          0 :                         return -1;
     267                 :            :                 }
     268                 :            : 
     269                 :         28 :                 data_ptr = calloc(1, psize);
     270                 :         28 :                 if (!data_ptr) {
     271                 :            :                         return -1;
     272                 :            :                 }
     273                 :            : 
     274                 :         28 :                 pactual = data_stat.st_size;
     275                 :            : 
     276                 :            :                 /*
     277                 :            :                  * There's two char device inputs we care about: /dev/zero and
     278                 :            :                  * /dev/urandom. Both have a stat.st_size of zero so read in
     279                 :            :                  * a full partition worth, accounting for ECC overhead.
     280                 :            :                  */
     281                 :         28 :                 if (!pactual && S_ISCHR(data_stat.st_mode)) {
     282                 :         28 :                         pactual = psize;
     283                 :            : 
     284                 :         28 :                         if (has_ecc(new_entry)) {
     285                 :         20 :                                 pactual = ecc_buffer_size_minus_ecc(pactual);
     286                 :            : 
     287                 :            :                                 /* ECC input size needs to be a multiple of 8 */
     288                 :         20 :                                 pactual = pactual & ~0x7;
     289                 :            :                         }
     290                 :            :                 }
     291                 :            :                 /*
     292                 :            :                  * Sanity check that the file isn't too large for
     293                 :            :                  * partition
     294                 :            :                  */
     295                 :         28 :                 if (has_ecc(new_entry) && !strstr(filename, ".ecc"))
     296                 :         20 :                         psize = ecc_buffer_size_minus_ecc(psize);
     297                 :         28 :                 if (pactual > psize) {
     298                 :          0 :                         fprintf(stderr, "File '%s' for partition '%s' is too large,"
     299                 :            :                                 " %u > %u\n",
     300                 :            :                                 filename, name, pactual, psize);
     301                 :          0 :                         close(data_fd);
     302                 :          0 :                         return -1;
     303                 :            :                 }
     304                 :            : 
     305                 :         56 :                 for (data_len = 0; data_len < pactual; data_len += rc) {
     306                 :         28 :                         rc = read(data_fd, &data_ptr[data_len], pactual - data_len);
     307                 :         28 :                         if (rc == -1) {
     308                 :          0 :                                 fprintf(stderr, "error reading from '%s'", filename);
     309                 :          0 :                                 exit(1);
     310                 :            :                         }
     311                 :            :                 }
     312                 :            : 
     313                 :         28 :                 rc = blocklevel_write(bl, pbase, data_ptr, pactual);
     314                 :         28 :                 if (rc) {
     315                 :          0 :                         fprintf(stderr, "Couldn't write file '%s' for '%s' partition to PNOR "
     316                 :            :                                         "(%m)\n", filename, name);
     317                 :          0 :                         exit(1);
     318                 :            :                 }
     319                 :            : 
     320                 :         28 :                 free(data_ptr);
     321                 :         28 :                 close(data_fd);
     322                 :            :         } else {
     323                 :          0 :                 if (!allow_empty) {
     324                 :          0 :                         fprintf(stderr, "Filename missing for partition %s!\n",
     325                 :            :                                         name);
     326                 :          0 :                         return -1;
     327                 :            :                 }
     328                 :          0 :                 if (has_ecc(new_entry)) {
     329                 :          0 :                         i = pbase + 8;
     330                 :          0 :                         while (i < pbase + psize) {
     331                 :          0 :                                 rc = blocklevel_write(bl, i, &ecc, sizeof(ecc));
     332                 :          0 :                                 if (rc) {
     333                 :          0 :                                         fprintf(stderr, "\nError setting ECC byte at 0x%08x\n",
     334                 :            :                                                         i);
     335                 :          0 :                                         return rc;
     336                 :            :                                 }
     337                 :          0 :                                 i += 9;
     338                 :            :                         }
     339                 :            :                 }
     340                 :            : 
     341                 :            :         }
     342                 :            : 
     343                 :            :         return 0;
     344                 :            : }
     345                 :            : 
     346                 :          0 : static void print_version(void)
     347                 :            : {
     348                 :          0 :         printf("Open-Power FFS format tool %s\n", version);
     349                 :            : }
     350                 :            : 
     351                 :          0 : static void print_help(const char *pname)
     352                 :            : {
     353                 :          0 :         print_version();
     354                 :          0 :         printf("Usage: %s [options] -e -s size -c num -i layout_file -p pnor_file ...\n\n", pname);
     355                 :          0 :         printf(" Options:\n");
     356                 :          0 :         printf("\t-e, --allow_empty\n");
     357                 :          0 :         printf("\t\tCreate partition as blank if not specified (sets ECC if flag set)\n\n");
     358                 :          0 :         printf("\t-s, --block_size=size\n");
     359                 :          0 :         printf("\t\tSize (in hex with leading 0x) of the blocks on the flash in bytes\n\n");
     360                 :          0 :         printf("\t-c, --block_count=num\n");
     361                 :          0 :         printf("\t\tNumber of blocks on the flash\n\n");
     362                 :          0 :         printf("\t-i, --input=file\n");
     363                 :          0 :         printf("\t\tFile containing the required partition data\n\n");
     364                 :          0 :         printf("\t-p, --pnor=file\n");
     365                 :          0 :         printf("\t\tOutput file to write data\n\n");
     366                 :          0 : }
     367                 :            : 
     368                 :          6 : int main(int argc, char *argv[])
     369                 :            : {
     370                 :          6 :         static char line[MAX_LINE];
     371                 :            : 
     372                 :          6 :         char *pnor = NULL, *input = NULL;
     373                 :          6 :         bool toc_created = false, bad_input = false, allow_empty = false;
     374                 :          6 :         uint32_t block_size = 0, block_count = 0;
     375                 :          6 :         struct ffs_hdr *tocs[MAX_TOCS] = { 0 };
     376                 :          6 :         struct blocklevel_device *bl = NULL;
     377                 :          6 :         const char *pname = argv[0];
     378                 :         30 :         int line_number, rc, i;
     379                 :         30 :         FILE *in_file;
     380                 :            : 
     381                 :         54 :         while(1) {
     382                 :         30 :                 struct option long_opts[] = {
     383                 :            :                         {"allow_empty", no_argument,          NULL,   'e'},
     384                 :            :                         {"block_count",       required_argument,      NULL,   'c'},
     385                 :            :                         {"block_size",        required_argument,      NULL,   's'},
     386                 :            :                         {"debug",     no_argument,            NULL,   'g'},
     387                 :            :                         {"input",     required_argument,      NULL,   'i'},
     388                 :            :                         {"pnor",      required_argument,      NULL,   'p'},
     389                 :            :                         {NULL,  0,      0, 0}
     390                 :            :                 };
     391                 :         30 :                 int c, oidx = 0;
     392                 :            : 
     393                 :         30 :                 c = getopt_long(argc, argv, "+:ec:gi:p:s:", long_opts, &oidx);
     394                 :         30 :                 if (c == EOF)
     395                 :            :                         break;
     396                 :         24 :                 switch(c) {
     397                 :            :                 case 'e':
     398                 :            :                         allow_empty = true;
     399                 :            :                         break;
     400                 :          6 :                 case 'c':
     401                 :          6 :                         block_count = strtoul(optarg, NULL, 0);
     402                 :          6 :                         break;
     403                 :          0 :                 case 'g':
     404                 :          0 :                         libflash_debug = true;
     405                 :          0 :                         break;
     406                 :          6 :                 case 'i':
     407                 :          6 :                         free(input);
     408                 :          6 :                         input = strdup(optarg);
     409                 :          6 :                         if (!input)
     410                 :          0 :                                 fprintf(stderr, "Out of memory!\n");
     411                 :            :                         break;
     412                 :          6 :                 case 'p':
     413                 :          6 :                         free(pnor);
     414                 :          6 :                         pnor = strdup(optarg);
     415                 :          6 :                         if (!pnor)
     416                 :         24 :                                 fprintf(stderr, "Out of memory!\n");
     417                 :            :                         break;
     418                 :          6 :                 case 's':
     419                 :          6 :                         block_size = strtoul(optarg, NULL, 0);
     420                 :          6 :                         break;
     421                 :          0 :                 case ':':
     422                 :          0 :                         fprintf(stderr, "Unrecognised option \"%s\" to '%c'\n",
     423                 :            :                                         optarg, optopt);
     424                 :          0 :                         bad_input = true;
     425                 :          0 :                         break;
     426                 :          0 :                 case '?':
     427                 :          0 :                         fprintf(stderr, "Unrecognised option '%c'\n", optopt);
     428                 :          0 :                         bad_input = true;
     429                 :          0 :                         break;
     430                 :          0 :                 default:
     431                 :          0 :                         fprintf(stderr , "Encountered unknown error parsing options\n");
     432                 :          0 :                         bad_input = true;
     433                 :            :                 }
     434                 :            :         }
     435                 :            : 
     436                 :          6 :         if (bad_input || !block_size || !block_count || !input || !pnor) {
     437                 :          0 :                 print_help(pname);
     438                 :          0 :                 return 1;
     439                 :            :         }
     440                 :            : 
     441                 :          6 :         in_file = fopen(input, "r");
     442                 :          6 :         if (!in_file) {
     443                 :          0 :                 fprintf(stderr, "Couldn't open your input file %s: %m\n", input);
     444                 :          0 :                 return 2;
     445                 :            :         }
     446                 :            : 
     447                 :            :         /*
     448                 :            :          * TODO: This won't create the file.
     449                 :            :          * We should do this
     450                 :            :          */
     451                 :          6 :         rc = arch_flash_init(&bl, pnor, true);
     452                 :          6 :         if (rc) {
     453                 :          0 :                 fprintf(stderr, "Couldn't initialise architecture flash structures\n");
     454                 :          0 :                 fclose(in_file);
     455                 :          0 :                 return 3;
     456                 :            :         }
     457                 :            : 
     458                 :            :         /*
     459                 :            :          * 'Erase' the file, make it all 0xFF
     460                 :            :          * TODO: Add sparse option and don't do this.
     461                 :            :          */
     462                 :          6 :         rc = blocklevel_erase(bl, 0, block_size * block_count);
     463                 :          6 :         if (rc) {
     464                 :          0 :                 fprintf(stderr, "Couldn't erase '%s' pnor file\n", pnor);
     465                 :          0 :                 fclose(in_file);
     466                 :          0 :                 return 4;
     467                 :            :         }
     468                 :            : 
     469                 :            :         line_number = 0;
     470                 :         34 :         while (fgets(line, MAX_LINE, in_file) != NULL) {
     471                 :         28 :                 line_number++;
     472                 :            : 
     473                 :            :                 /* Inline comments in input file */
     474                 :         28 :                 if (line[0] == '#')
     475                 :          0 :                         continue;
     476                 :            : 
     477                 :         28 :                 if (line[strlen(line) - 1] == '\n')
     478                 :         28 :                         line[strlen(line) - 1] = '\0';
     479                 :            : 
     480                 :         28 :                 if (line[0] == '@') {
     481                 :          0 :                         int toc_num = line[1];
     482                 :          0 :                         rc = 5;
     483                 :            : 
     484                 :          0 :                         if (!isdigit(toc_num)) {
     485                 :          0 :                                 fprintf(stderr, "Invalid TOC ID %d (%c)\n",
     486                 :            :                                                 toc_num, toc_num);
     487                 :          0 :                                 goto parse_out;
     488                 :            :                         }
     489                 :            : 
     490                 :          0 :                         toc_num -= '0';
     491                 :            : 
     492                 :          0 :                         if (line[2] != SEPARATOR) {
     493                 :          0 :                                 fprintf(stderr, "TOC ID too long\n");
     494                 :          0 :                                 goto parse_out;
     495                 :            :                         }
     496                 :            : 
     497                 :          0 :                         if (tocs[toc_num]) {
     498                 :          0 :                                 fprintf(stderr, "Duplicate TOC ID %d\n", toc_num);
     499                 :          0 :                                 goto parse_out;
     500                 :            :                         }
     501                 :            : 
     502                 :          0 :                         tocs[toc_num] = parse_toc(&line[3], block_size, block_count);
     503                 :          0 :                         if (!tocs[toc_num])
     504                 :          0 :                                 goto parse_out;
     505                 :            :                         toc_created = true;
     506                 :            :                 } else {
     507                 :         28 :                         if (!toc_created) {
     508                 :          6 :                                 fprintf(stderr, "WARNING: Attempting to parse a partition line without any TOCs created.\n");
     509                 :          6 :                                 fprintf(stderr, "         Generating a default TOC at zero\n");
     510                 :          6 :                                 rc = ffs_hdr_new(block_size, block_count, NULL, &tocs[0]);
     511                 :          6 :                                 if (rc) {
     512                 :          0 :                                         rc = 7;
     513                 :          0 :                                         fprintf(stderr, "Couldn't generate a default TOC at zero\n");
     514                 :          0 :                                         goto parse_out;
     515                 :            :                                 }
     516                 :            :                                 toc_created = true;
     517                 :            :                         }
     518                 :         28 :                         rc = parse_entry(bl, tocs, line, allow_empty);
     519                 :         28 :                         if (rc) {
     520                 :          0 :                                 rc = 6;
     521                 :          0 :                                 goto parse_out;
     522                 :            :                         }
     523                 :            :                 }
     524                 :            :         }
     525                 :            : 
     526                 :         66 :         for(i = 0; i < MAX_TOCS; i++) {
     527                 :         60 :                 if (tocs[i]) {
     528                 :          6 :                         rc = ffs_hdr_finalise(bl, tocs[i]);
     529                 :          6 :                         if (rc) {
     530                 :          0 :                                 rc = 7;
     531                 :          0 :                                 fprintf(stderr, "Failed to write out TOC values\n");
     532                 :            :                                 break;
     533                 :            :                         }
     534                 :            :                 }
     535                 :            :         }
     536                 :            : 
     537                 :          6 : parse_out:
     538                 :          6 :         if (rc == 5 || rc == 6)
     539                 :          0 :                 fprintf(stderr, "Failed to parse input file '%s' at line %d\n",
     540                 :            :                                 input, line_number);
     541                 :          6 :         arch_flash_close(bl, pnor);
     542                 :          6 :         fclose(in_file);
     543                 :         72 :         for(i = 0; i < MAX_TOCS; i++)
     544                 :         60 :                 ffs_hdr_free(tocs[i]);
     545                 :          6 :         free(input);
     546                 :          6 :         free(pnor);
     547                 :          6 :         return rc;
     548                 :            : }

Generated by: LCOV version 1.14