summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/bcm63xxpart.c
diff options
context:
space:
mode:
authorSimon Arlott <simon@fire.lp0.eu>2015-12-13 17:51:02 -0500
committerBrian Norris <computersforpeace@gmail.com>2016-02-12 13:34:15 -0500
commit7fffa694a8917af0c553ab48290a57e3674aa5d3 (patch)
tree4e5a867fcc8fdd8cb4363f3666463af0b609fa8a /drivers/mtd/bcm63xxpart.c
parent436e94a6fbcdca133a2546769db4ac0a84265ad1 (diff)
mtd: bcm63xxpart: Extract read of image tag to separate function
Extract image tag reading and CRC check to a separate function. Signed-off-by: Simon Arlott <simon@fire.lp0.eu> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/bcm63xxpart.c')
-rw-r--r--drivers/mtd/bcm63xxpart.c62
1 files changed, 40 insertions, 22 deletions
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 1eea8b6bc66a..eafbf521a547 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -41,6 +41,10 @@
41#define BCM963XX_CFE_VERSION_OFFSET 0x570 41#define BCM963XX_CFE_VERSION_OFFSET 0x570
42#define BCM963XX_NVRAM_OFFSET 0x580 42#define BCM963XX_NVRAM_OFFSET 0x580
43 43
44/* Ensure strings read from flash structs are null terminated */
45#define STR_NULL_TERMINATE(x) \
46 do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0)
47
44static int bcm63xx_detect_cfe(struct mtd_info *master) 48static int bcm63xx_detect_cfe(struct mtd_info *master)
45{ 49{
46 char buf[9]; 50 char buf[9];
@@ -89,6 +93,37 @@ static int bcm63xx_read_nvram(struct mtd_info *master,
89 return 0; 93 return 0;
90} 94}
91 95
96static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name,
97 loff_t tag_offset, struct bcm_tag *buf)
98{
99 int ret;
100 size_t retlen;
101 u32 computed_crc;
102
103 ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf);
104 if (ret)
105 return ret;
106
107 if (retlen != sizeof(*buf))
108 return -EIO;
109
110 computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
111 offsetof(struct bcm_tag, header_crc));
112 if (computed_crc == buf->header_crc) {
113 STR_NULL_TERMINATE(buf->board_id);
114 STR_NULL_TERMINATE(buf->tag_version);
115
116 pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n",
117 name, tag_offset, buf->tag_version, buf->board_id);
118
119 return 0;
120 }
121
122 pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n",
123 name, tag_offset, buf->header_crc, computed_crc);
124 return 1;
125}
126
92static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, 127static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
93 const struct mtd_partition **pparts, 128 const struct mtd_partition **pparts,
94 struct mtd_part_parser_data *data) 129 struct mtd_part_parser_data *data)
@@ -99,13 +134,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
99 struct bcm_tag *buf = NULL; 134 struct bcm_tag *buf = NULL;
100 struct mtd_partition *parts; 135 struct mtd_partition *parts;
101 int ret; 136 int ret;
102 size_t retlen;
103 unsigned int rootfsaddr, kerneladdr, spareaddr; 137 unsigned int rootfsaddr, kerneladdr, spareaddr;
104 unsigned int rootfslen, kernellen, sparelen, totallen; 138 unsigned int rootfslen, kernellen, sparelen, totallen;
105 unsigned int cfelen, nvramlen; 139 unsigned int cfelen, nvramlen;
106 unsigned int cfe_erasesize; 140 unsigned int cfe_erasesize;
107 int i; 141 int i;
108 u32 computed_crc;
109 bool rootfs_first = false; 142 bool rootfs_first = false;
110 143
111 if (bcm63xx_detect_cfe(master)) 144 if (bcm63xx_detect_cfe(master))
@@ -134,28 +167,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
134 } 167 }
135 168
136 /* Get the tag */ 169 /* Get the tag */
137 ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen, 170 ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf);
138 (void *)buf); 171 if (!ret) {
139
140 if (retlen != sizeof(struct bcm_tag)) {
141 ret = -EIO;
142 goto out;
143 }
144
145 computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
146 offsetof(struct bcm_tag, header_crc));
147 if (computed_crc == buf->header_crc) {
148 char *boardid = &(buf->board_id[0]);
149 char *tagversion = &(buf->tag_version[0]);
150
151 sscanf(buf->flash_image_start, "%u", &rootfsaddr); 172 sscanf(buf->flash_image_start, "%u", &rootfsaddr);
152 sscanf(buf->kernel_address, "%u", &kerneladdr); 173 sscanf(buf->kernel_address, "%u", &kerneladdr);
153 sscanf(buf->kernel_length, "%u", &kernellen); 174 sscanf(buf->kernel_length, "%u", &kernellen);
154 sscanf(buf->total_length, "%u", &totallen); 175 sscanf(buf->total_length, "%u", &totallen);
155 176
156 pr_info("CFE boot tag found with version %s and board type %s\n",
157 tagversion, boardid);
158
159 kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE; 177 kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
160 rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE; 178 rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
161 spareaddr = roundup(totallen, master->erasesize) + cfelen; 179 spareaddr = roundup(totallen, master->erasesize) + cfelen;
@@ -169,13 +187,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
169 rootfsaddr = kerneladdr + kernellen; 187 rootfsaddr = kerneladdr + kernellen;
170 rootfslen = spareaddr - rootfsaddr; 188 rootfslen = spareaddr - rootfsaddr;
171 } 189 }
172 } else { 190 } else if (ret > 0) {
173 pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
174 buf->header_crc, computed_crc);
175 kernellen = 0; 191 kernellen = 0;
176 rootfslen = 0; 192 rootfslen = 0;
177 rootfsaddr = 0; 193 rootfsaddr = 0;
178 spareaddr = cfelen; 194 spareaddr = cfelen;
195 } else {
196 goto out;
179 } 197 }
180 sparelen = master->size - spareaddr - nvramlen; 198 sparelen = master->size - spareaddr - nvramlen;
181 199