barebox/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
Sascha Hauer cb8cf33ce8 fix erasing/protecting flashes with unspecified size
fixes: 81737c1 mtd: Fix erasing of devices >4GiB

Several places erased a complete flash partition passing ~0 as count to
erase(). With the above commit count to erase was changed from an unsigned
type to a signed type, so the (count > f->size - offset) check in
erase() no longer triggers and the ~0 count is no longer adjusted to the whole
device size. Among other things this results in saveenv failures on NOR
flashes.
This patch fixes this by introducing an explicit macro for erasing the
whole device which is tested for in erase(). All other negative values
are rejected.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reported-by: Giorgio <giorgio.nicole@arcor.de>
2016-04-19 08:26:51 +02:00

120 lines
2.6 KiB
C

/*
* am33xx_bbu_spi_mlo.c - am35xx and am33xx specific MLO
* update handler for SPI NOR flash
*
* Copyright (c) 2013 Sharavn kumar <shravan.k@phytec.in>, Phytec
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <common.h>
#include <malloc.h>
#include <bbu.h>
#include <fs.h>
#include <fcntl.h>
#include <linux/stat.h>
/*
* AM35xx, AM33xx chips use big endian MLO for SPI NOR flash
* This handler converting MLO to big endian and write to SPI NOR
*/
static int spi_nor_mlo_handler(struct bbu_handler *handler,
struct bbu_data *data)
{
int dstfd = 0;
int ret = 0;
uint32_t readbuf;
int size = data->len;
void *image = data->image;
uint32_t *header;
int swap = 0;
struct stat s;
header = data->image;
if (header[5] == 0x43485345 || header[10] == 0x62617265) {
swap = 0;
} else if (header[5] == 0x45534843 || header[10] == 0x65726142) {
swap = 1;
} else {
if (!bbu_force(data, "Not a MLO image"))
return -EINVAL;
}
ret = stat(data->devicefile, &s);
if (ret) {
printf("could not open %s: %s", data->devicefile, errno_str());
return ret;
}
if (size > s.st_size) {
printf("Image too big, need %d, have %lld\n", size, s.st_size);
return -ENOSPC;
}
ret = bbu_confirm(data);
if (ret != 0)
return ret;
dstfd = open(data->devicefile, O_WRONLY);
if (dstfd < 0) {
printf("could not open %s: %s", data->devicefile, errno_str());
ret = dstfd;
goto out;
}
ret = erase(dstfd, ERASE_SIZE_ALL, 0);
if (ret < 0) {
printf("could not erase %s: %s", data->devicefile, errno_str());
goto out1;
}
for (; size >= 0; size -= 4) {
memcpy((char *)&readbuf, image, 4);
if (swap)
readbuf = cpu_to_be32(readbuf);
ret = write(dstfd, &readbuf, 4);
if (ret < 0) {
perror("write");
goto out1;
}
image = image + 4;
}
ret = 0;
out1:
close(dstfd);
out:
return ret;
}
/*
* Register a am33xx MLO update handler for SPI NOR
*/
int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile)
{
struct bbu_handler *handler;
int ret;
handler = xzalloc(sizeof(*handler));
handler->devicefile = devicefile;
handler->name = name;
handler->handler = spi_nor_mlo_handler;
ret = bbu_register_handler(handler);
if (ret)
free(handler);
return ret;
}