#include "mtdsplit.h"
+/*
+ * uimage_header itself is only 64B, but it may be prepended with another data.
+ * Currently the biggest size is for Edimax devices: 20B + 64B
+ */
+#define MAX_HEADER_LEN 84
+
#define IH_MAGIC 0x27051956 /* Image Magic Number */
#define IH_NMLEN 32 /* Image Name Length */
};
static int
-read_uimage_header(struct mtd_info *mtd, size_t offset,
- struct uimage_header *header)
+read_uimage_header(struct mtd_info *mtd, size_t offset, u_char *buf,
+ size_t header_len)
{
- size_t header_len;
size_t retlen;
int ret;
- header_len = sizeof(*header);
- ret = mtd_read(mtd, offset, header_len, &retlen,
- (unsigned char *) header);
+ ret = mtd_read(mtd, offset, header_len, &retlen, buf);
if (ret) {
pr_debug("read error in \"%s\"\n", mtd->name);
return ret;
ssize_t (*find_header)(u_char *buf, size_t len))
{
struct mtd_partition *parts;
- struct uimage_header *header;
+ u_char *buf;
int nr_parts;
size_t offset;
size_t uimage_offset;
if (!parts)
return -ENOMEM;
- header = vmalloc(sizeof(*header));
- if (!header) {
+ buf = vmalloc(MAX_HEADER_LEN);
+ if (!buf) {
ret = -ENOMEM;
goto err_free_parts;
}
/* find uImage on erase block boundaries */
for (offset = 0; offset < master->size; offset += master->erasesize) {
+ struct uimage_header *header;
+
uimage_size = 0;
- ret = read_uimage_header(master, offset, header);
+ ret = read_uimage_header(master, offset, buf, MAX_HEADER_LEN);
if (ret)
continue;
- ret = find_header((u_char *)header, sizeof(*header));
+ ret = find_header(buf, MAX_HEADER_LEN);
if (ret < 0) {
pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
master->name, (unsigned long long) offset);
continue;
}
- if (ret > 0) {
- pr_warn("extra header offsets are not supported yet\n");
- continue;
- }
+ header = (struct uimage_header *)(buf + ret);
uimage_size = sizeof(*header) + be32_to_cpu(header->ih_size);
if ((offset + uimage_size) > master->size) {
if (uimage_size == 0) {
pr_debug("no uImage found in \"%s\"\n", master->name);
ret = -ENODEV;
- goto err_free_header;
+ goto err_free_buf;
}
uimage_offset = offset;
if (ret) {
pr_debug("no rootfs after uImage in \"%s\"\n",
master->name);
- goto err_free_header;
+ goto err_free_buf;
}
rootfs_size = master->size - rootfs_offset;
if (ret) {
pr_debug("no rootfs before uImage in \"%s\"\n",
master->name);
- goto err_free_header;
+ goto err_free_buf;
}
rootfs_offset = 0;
if (rootfs_size == 0) {
pr_debug("no rootfs found in \"%s\"\n", master->name);
ret = -ENODEV;
- goto err_free_header;
+ goto err_free_buf;
}
parts[uimage_part].name = KERNEL_PART_NAME;
parts[rf_part].offset = rootfs_offset;
parts[rf_part].size = rootfs_size;
- vfree(header);
+ vfree(buf);
*pparts = parts;
return nr_parts;
-err_free_header:
- vfree(header);
+err_free_buf:
+ vfree(buf);
err_free_parts:
kfree(parts);
#define FW_MAGIC_WNR1000V2_VC 0x31303030
#define FW_MAGIC_WNDR3700 0x33373030
#define FW_MAGIC_WNDR3700V2 0x33373031
+#define FW_MAGIC_WPN824N 0x31313030
static ssize_t uimage_verify_wndr3700(u_char *buf, size_t len)
{
case FW_MAGIC_WNR2200:
case FW_MAGIC_WNDR3700:
case FW_MAGIC_WNDR3700V2:
+ case FW_MAGIC_WPN824N:
break;
case FW_MAGIC_WNR2000V4:
expected_type = IH_TYPE_KERNEL;