mtdsplit_uimage: more generic header verify function
Some devices have uImage headers after some extra headers (e.g. Edimax devices). To support such cases our verify callback function should be allowed to return header offset, not just a boolean value. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 44412
This commit is contained in:
parent
1f3cdb8634
commit
1aed104c80
1 changed files with 26 additions and 11 deletions
|
@ -71,10 +71,16 @@ read_uimage_header(struct mtd_info *mtd, size_t offset,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __mtdsplit_parse_uimage - scan partition and create kernel + rootfs parts
|
||||||
|
*
|
||||||
|
* @find_header: function to call for a block of data that will return offset
|
||||||
|
* of a valid uImage header if found
|
||||||
|
*/
|
||||||
static int __mtdsplit_parse_uimage(struct mtd_info *master,
|
static int __mtdsplit_parse_uimage(struct mtd_info *master,
|
||||||
struct mtd_partition **pparts,
|
struct mtd_partition **pparts,
|
||||||
struct mtd_part_parser_data *data,
|
struct mtd_part_parser_data *data,
|
||||||
bool (*verify)(struct uimage_header *hdr))
|
ssize_t (*find_header)(u_char *buf, size_t len))
|
||||||
{
|
{
|
||||||
struct mtd_partition *parts;
|
struct mtd_partition *parts;
|
||||||
struct uimage_header *header;
|
struct uimage_header *header;
|
||||||
|
@ -106,11 +112,16 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master,
|
||||||
if (ret)
|
if (ret)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!verify(header)) {
|
ret = find_header((u_char *)header, sizeof(*header));
|
||||||
|
if (ret < 0) {
|
||||||
pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
|
pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
|
||||||
master->name, (unsigned long long) offset);
|
master->name, (unsigned long long) offset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (ret > 0) {
|
||||||
|
pr_warn("extra header offsets are not supported yet\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uimage_size = sizeof(*header) + be32_to_cpu(header->ih_size);
|
uimage_size = sizeof(*header) + be32_to_cpu(header->ih_size);
|
||||||
if ((offset + uimage_size) > master->size) {
|
if ((offset + uimage_size) > master->size) {
|
||||||
|
@ -189,28 +200,30 @@ err_free_parts:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool uimage_verify_default(struct uimage_header *header)
|
static ssize_t uimage_verify_default(u_char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
struct uimage_header *header = (struct uimage_header *)buf;
|
||||||
|
|
||||||
/* default sanity checks */
|
/* default sanity checks */
|
||||||
if (be32_to_cpu(header->ih_magic) != IH_MAGIC) {
|
if (be32_to_cpu(header->ih_magic) != IH_MAGIC) {
|
||||||
pr_debug("invalid uImage magic: %08x\n",
|
pr_debug("invalid uImage magic: %08x\n",
|
||||||
be32_to_cpu(header->ih_magic));
|
be32_to_cpu(header->ih_magic));
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->ih_os != IH_OS_LINUX) {
|
if (header->ih_os != IH_OS_LINUX) {
|
||||||
pr_debug("invalid uImage OS: %08x\n",
|
pr_debug("invalid uImage OS: %08x\n",
|
||||||
be32_to_cpu(header->ih_os));
|
be32_to_cpu(header->ih_os));
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->ih_type != IH_TYPE_KERNEL) {
|
if (header->ih_type != IH_TYPE_KERNEL) {
|
||||||
pr_debug("invalid uImage type: %08x\n",
|
pr_debug("invalid uImage type: %08x\n",
|
||||||
be32_to_cpu(header->ih_type));
|
be32_to_cpu(header->ih_type));
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -238,9 +251,11 @@ static struct mtd_part_parser uimage_generic_parser = {
|
||||||
#define FW_MAGIC_WNDR3700 0x33373030
|
#define FW_MAGIC_WNDR3700 0x33373030
|
||||||
#define FW_MAGIC_WNDR3700V2 0x33373031
|
#define FW_MAGIC_WNDR3700V2 0x33373031
|
||||||
|
|
||||||
static bool uimage_verify_wndr3700(struct uimage_header *header)
|
static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
struct uimage_header *header = (struct uimage_header *)buf;
|
||||||
uint8_t expected_type = IH_TYPE_FILESYSTEM;
|
uint8_t expected_type = IH_TYPE_FILESYSTEM;
|
||||||
|
|
||||||
switch be32_to_cpu(header->ih_magic) {
|
switch be32_to_cpu(header->ih_magic) {
|
||||||
case FW_MAGIC_WNR612V2:
|
case FW_MAGIC_WNR612V2:
|
||||||
case FW_MAGIC_WNR1000V2:
|
case FW_MAGIC_WNR1000V2:
|
||||||
|
@ -254,14 +269,14 @@ static bool uimage_verify_wndr3700(struct uimage_header *header)
|
||||||
expected_type = IH_TYPE_KERNEL;
|
expected_type = IH_TYPE_KERNEL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->ih_os != IH_OS_LINUX ||
|
if (header->ih_os != IH_OS_LINUX ||
|
||||||
header->ih_type != expected_type)
|
header->ih_type != expected_type)
|
||||||
return false;
|
return -EINVAL;
|
||||||
|
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in a new issue