| From 43b9a7c9b903302c56d0a1d292a146dbf4de8e49 Mon Sep 17 00:00:00 2001 |
| From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> |
| Date: Mon, 12 Aug 2013 01:17:08 +0200 |
| Subject: tools: lantiq: add NAND SPL support |
| |
| Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> |
| |
| --- a/tools/ltq-boot-image.c |
| +++ b/tools/ltq-boot-image.c |
| @@ -14,7 +14,8 @@ |
| |
| enum image_types { |
| IMAGE_NONE, |
| - IMAGE_SFSPL |
| + IMAGE_SFSPL, |
| + IMAGE_NANDSPL |
| }; |
| |
| /* Lantiq non-volatile bootstrap command IDs */ |
| @@ -43,6 +44,8 @@ enum nvb_cmd_flags { |
| struct args { |
| enum image_types type; |
| __u32 entry_addr; |
| + off_t uboot_offset; |
| + unsigned int page_size; |
| const char *uboot_bin; |
| const char *spl_bin; |
| const char *out_bin; |
| @@ -50,10 +53,11 @@ struct args { |
| |
| static void usage_msg(const char *name) |
| { |
| - fprintf(stderr, "%s: [-h] -t type -e entry-addr -u uboot-bin [-s spl-bin] -o out-bin\n", |
| + fprintf(stderr, "%s: [-h] -t type -e entry-addr [-x uboot-offset] [-p page-size] -u uboot-bin [-s spl-bin] -o out-bin\n", |
| name); |
| fprintf(stderr, " Image types:\n" |
| - " sfspl - SPL + [compressed] U-Boot for SPI flash\n"); |
| + " sfspl - SPL + [compressed] U-Boot for SPI flash\n" |
| + " nandspl - SPL + [compressed] U-Boot for NAND flash\n"); |
| } |
| |
| static enum image_types parse_image_type(const char *type) |
| @@ -64,6 +68,9 @@ static enum image_types parse_image_type |
| if (!strncmp(type, "sfspl", 6)) |
| return IMAGE_SFSPL; |
| |
| + if (!strncmp(type, "nandspl", 6)) |
| + return IMAGE_NANDSPL; |
| + |
| return IMAGE_NONE; |
| } |
| |
| @@ -73,7 +80,7 @@ static int parse_args(int argc, char *ar |
| |
| memset(arg, 0, sizeof(*arg)); |
| |
| - while ((opt = getopt(argc, argv, "ht:e:u:s:o:")) != -1) { |
| + while ((opt = getopt(argc, argv, "ht:e:x:p:u:s:o:")) != -1) { |
| switch (opt) { |
| case 'h': |
| usage_msg(argv[0]); |
| @@ -84,6 +91,12 @@ static int parse_args(int argc, char *ar |
| case 'e': |
| arg->entry_addr = strtoul(optarg, NULL, 16); |
| break; |
| + case 'x': |
| + arg->uboot_offset = strtoul(optarg, NULL, 16); |
| + break; |
| + case 'p': |
| + arg->page_size = strtoul(optarg, NULL, 10); |
| + break; |
| case 'u': |
| arg->uboot_bin = optarg; |
| break; |
| @@ -114,11 +127,22 @@ static int parse_args(int argc, char *ar |
| goto parse_error; |
| } |
| |
| - if (arg->type == IMAGE_SFSPL && !arg->spl_bin) { |
| + if ((arg->type == IMAGE_SFSPL || arg->type == IMAGE_NANDSPL) && |
| + !arg->spl_bin) { |
| fprintf(stderr, "Missing SPL binary\n"); |
| goto parse_error; |
| } |
| |
| + if (arg->type == IMAGE_NANDSPL && !arg->uboot_offset) { |
| + fprintf(stderr, "Missing U-Boot offset\n"); |
| + goto parse_error; |
| + } |
| + |
| + if (arg->type == IMAGE_NANDSPL && !arg->page_size) { |
| + fprintf(stderr, "Missing NAND page size\n"); |
| + goto parse_error; |
| + } |
| + |
| return 0; |
| |
| parse_error: |
| @@ -174,6 +198,19 @@ static int write_nvb_start_header(int fd |
| return write_header(fd, hdr, sizeof(hdr)); |
| } |
| |
| +#if 0 |
| +static int write_nvb_regcfg_header(int fd, __u32 addr) |
| +{ |
| + __u32 hdr[2]; |
| + |
| + hdr[0] = build_nvb_command(NVB_CMD_REGCFG, NVB_FLAG_SDBG | |
| + NVB_FLAG_DBG); |
| + hdr[1] = cpu_to_be32(addr); |
| + |
| + return write_header(fd, hdr, sizeof(hdr)); |
| +} |
| +#endif |
| + |
| static int open_input_bin(const char *name, void **ptr, size_t *size) |
| { |
| struct stat sbuf; |
| @@ -238,9 +275,37 @@ static int open_output_bin(const char *n |
| return fd; |
| } |
| |
| -static int create_sfspl(const struct args *arg) |
| +static int pad_to_offset(int fd, off_t offset) |
| { |
| - int out_fd, uboot_fd, spl_fd, ret; |
| + off_t pos; |
| + size_t size; |
| + ssize_t n; |
| + __u8 *buf; |
| + |
| + pos = lseek(fd, 0, SEEK_CUR); |
| + size = offset - pos; |
| + |
| + buf = malloc(size); |
| + if (!buf) { |
| + fprintf(stderr, "Failed to malloc buffer\n"); |
| + return -1; |
| + } |
| + |
| + memset(buf, 0xff, size); |
| + n = write(fd, buf, size); |
| + free(buf); |
| + |
| + if (n != size) { |
| + fprintf(stderr, "Failed to write pad bytes\n"); |
| + return -1; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static int create_spl_image(const struct args *arg) |
| +{ |
| + int out_fd, uboot_fd, spl_fd, ret = 0; |
| void *uboot_ptr, *spl_ptr; |
| size_t uboot_size, spl_size; |
| |
| @@ -256,9 +321,22 @@ static int create_sfspl(const struct arg |
| if (0 > uboot_fd) |
| goto err_uboot; |
| |
| +#if 0 |
| + ret = write_nvb_regcfg_header(out_fd, 0); |
| + if (ret) |
| + goto err_write; |
| +#endif |
| + |
| ret = write_nvb_dwnld_header(out_fd, spl_size, arg->entry_addr); |
| if (ret) |
| goto err_write; |
| +#if 0 |
| + if (arg->page_size) { |
| + ret = pad_to_offset(out_fd, arg->page_size); |
| + if (ret) |
| + goto err_write; |
| + } |
| +#endif |
| |
| ret = copy_bin(out_fd, spl_ptr, spl_size); |
| if (ret) |
| @@ -268,16 +346,16 @@ static int create_sfspl(const struct arg |
| if (ret) |
| goto err_write; |
| |
| + if (arg->uboot_offset) { |
| + ret = pad_to_offset(out_fd, arg->uboot_offset); |
| + if (ret) |
| + goto err_write; |
| + } |
| + |
| ret = copy_bin(out_fd, uboot_ptr, uboot_size); |
| if (ret) |
| goto err_write; |
| |
| - close_input_bin(uboot_fd, uboot_ptr, uboot_size); |
| - close_input_bin(spl_fd, spl_ptr, spl_size); |
| - close(out_fd); |
| - |
| - return 0; |
| - |
| err_write: |
| close_input_bin(uboot_fd, uboot_ptr, uboot_size); |
| err_uboot: |
| @@ -285,7 +363,7 @@ err_uboot: |
| err_spl: |
| close(out_fd); |
| err: |
| - return -1; |
| + return ret; |
| } |
| |
| int main(int argc, char *argv[]) |
| @@ -299,7 +377,8 @@ int main(int argc, char *argv[]) |
| |
| switch (arg.type) { |
| case IMAGE_SFSPL: |
| - ret = create_sfspl(&arg); |
| + case IMAGE_NANDSPL: |
| + ret = create_spl_image(&arg); |
| break; |
| default: |
| fprintf(stderr, "Image type not implemented\n"); |