2 * Copyright (C) 2015 IBM Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
20 #include <asm/byteorder.h>
23 #include <talloc/talloc.h>
24 #include <flash/flash.h>
25 #include <ccan/endian/endian.h>
27 #include <libflash/arch_flash.h>
28 #include <libflash/blocklevel.h>
29 #include <libflash/libflash.h>
30 #include <libflash/libffs.h>
31 #include <libflash/file.h>
32 #include <libflash/ecc.h>
36 /* Device information */
37 struct blocklevel_device *bl;
38 struct ffs_handle *ffs;
39 uint64_t size; /* raw size of partition */
42 uint32_t erase_granule;
44 /* Partition information */
45 uint32_t attr_part_idx;
46 uint32_t attr_data_pos;
47 uint32_t attr_data_len; /* Includes ECC bytes */
49 /* 'Other Side' info if present */
50 struct flash_info *other_side;
54 static int partition_info(struct flash_info *info, const char *partition)
58 rc = ffs_lookup_part(info->ffs, partition, &info->attr_part_idx);
60 pb_log("Failed to find %s partition\n", partition);
64 return ffs_part_info(info->ffs, info->attr_part_idx, NULL,
65 &info->attr_data_pos, &info->attr_data_len,
69 static struct flash_info *flash_setup_buffer(void *ctx, const char *partition)
71 struct flash_info *info;
72 struct ffs_handle *tmp = NULL;
78 info = talloc_zero(ctx, struct flash_info);
82 rc = arch_flash_init(&info->bl, NULL, true);
84 pb_log("Failed to init mtd device\n");
88 rc = blocklevel_get_info(info->bl, &info->path, &info->size,
89 &info->erase_granule);
91 pb_log("Failed to retrieve blocklevel info\n");
95 rc = ffs_init(0, info->size, info->bl, &info->ffs, 1);
97 pb_log_fn("Failed to init ffs\n");
101 rc = partition_info(info, partition);
103 pb_log("Failed to retrieve partition info\n");
107 /* Check if there is a second flash side. If there is not, or
108 * we fail to recognise it, ignore it and continue */
109 ffs_next_side(info->ffs, &tmp, info->ecc);
110 if (tmp && ffs_equal(info->ffs, tmp) == false) {
111 pb_debug("Other side present on MTD device\n");
112 info->other_side = talloc_zero(info, struct flash_info);
113 info->other_side->ffs = tmp;
114 info->other_side->bl = info->bl;
115 info->other_side->size = info->size;
116 info->other_side->path = info->path;
117 info->other_side->ecc = info->ecc;
118 info->other_side->erase_granule = info->erase_granule;
119 rc = partition_info(info->other_side, partition);
121 pb_log("Failed to retrieve partition info "
122 "for other side - ignoring\n");
125 pb_debug("%s Details\n", partition);
126 pb_debug("\tName\t\t%s\n", info->path);
127 pb_debug("\tFlash Size\t%lu\n", info->size);
128 pb_debug("\tGranule\t\t%u\n", info->erase_granule);
129 pb_debug("\tECC\t\t%s\n", info->ecc ? "Protected" : "Unprotected");
130 pb_debug("\tCurrent Side info:\n");
131 pb_debug("\tIndex\t\t%u\n", info->attr_part_idx);
132 pb_debug("\tOffset\t\t%u\n", info->attr_data_pos);
133 pb_debug("\tPart. Size\t%u\n", info->attr_data_len);
134 if (info->other_side) {
135 pb_debug("\tOther Side info:\n");
136 pb_debug("\tIndex\t\t%u\n", info->other_side->attr_part_idx);
137 pb_debug("\tOffset\t\t%u\n", info->other_side->attr_data_pos);
138 pb_debug("\tPart. Size\t%u\n", info->other_side->attr_data_len);
143 ffs_close(info->ffs);
145 arch_flash_close(info->bl, NULL);
151 int flash_parse_version(void *ctx, char ***versions, bool current)
153 char *saveptr, *tok, **tmp, *buffer;
154 const char *delim = "\n";
155 struct flash_info *info, *cur_info;
159 saveptr = tok = NULL;
162 info = flash_setup_buffer(ctx, "VERSION");
166 if (!current && !info->other_side)
169 cur_info = !current ? info->other_side : info;
171 len = cur_info->attr_data_len - ecc_size(cur_info->attr_data_len);
172 buffer = talloc_array(cur_info, char, len);
174 pb_log_fn("Failed to init buffer!\n");
178 rc = blocklevel_read(cur_info->bl, cur_info->attr_data_pos,
181 pb_log("Failed to read VERSION partition\n");
185 /* open-power-platform */
186 tok = strtok_r(buffer, delim, &saveptr);
188 tmp = talloc_realloc(ctx, tmp, char *, n + 1);
190 pb_log_fn("Failed to allocate memory\n");
193 tmp[n++] = talloc_strdup(ctx, tok);
196 tok = strtok_r(NULL, delim, &saveptr);
198 /* Ignore leading tab from subsequent lines */
199 tmp = talloc_realloc(ctx, tmp, char *, n + 1);
201 pb_log_fn("Failed to reallocate memory\n");
205 tmp[n++] = talloc_strdup(ctx, tok + 1);
206 tok = strtok_r(NULL, delim, &saveptr);
210 pb_debug("%d version strings read from %s side\n",
211 n, current ? "current" : "other");
212 arch_flash_close(info->bl, NULL);