diff options
-rw-r--r-- | target/linux/brcm63xx/image/Makefile | 48 | ||||
-rw-r--r-- | tools/firmware-utils/Makefile | 3 | ||||
-rw-r--r-- | tools/firmware-utils/src/imagetag.c | 517 | ||||
-rw-r--r-- | tools/firmware-utils/src/imagetag.ggo | 45 | ||||
-rw-r--r-- | tools/firmware-utils/src/imagetag_cmdline.c | 1163 | ||||
-rw-r--r-- | tools/firmware-utils/src/imagetag_cmdline.h | 272 |
6 files changed, 1806 insertions, 242 deletions
diff --git a/target/linux/brcm63xx/image/Makefile b/target/linux/brcm63xx/image/Makefile index e2d63be34..56d048bbb 100644 --- a/target/linux/brcm63xx/image/Makefile +++ b/target/linux/brcm63xx/image/Makefile @@ -30,30 +30,32 @@ endef define Image/Build/CFE # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin \ - -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -r "$(5)" $(6) -# -b $(2) -c $(3) -e $(KERNEL_ENTRY) -l $(LOADADDR) - + --output $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin \ + --boardid $(2) --chipid $(3) --entry $(KERNEL_ENTRY) \ + --load-addr $(LOADADDR) --rsa-signature "$(5)" \ + --info1 "$(4) $(REVISION)" --info2 $(1) \ + $(6) $(7) $(8) $(9) endef define Image/Build/CFEAGPF # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ - -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -v 8 -m IMAGE -k 0x20000 -n $(4) + --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ + --boardid $(2) --chipid $(3) --entry $(LOADADDR) \ + --load-addr $(LOADADDR) --tag-version 8 \ + --signature2 IMAGE --block-size 0x20000 \ + --image-offset $(4) --info1 "$(5) $(REVISION)" --info2 $(1) endef define Image/Build/RG100A # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ - -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -k 0x20000 -n $(4) + --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ + --boardid $(2) --chipid $(3) --entry $(LOADADDR) \ + --load-addr $(LOADADDR) --block-size 0x20000 \ + --image-offset $(4) --info1 "$(5) $(REVISION)" --info2 $(1) endef - define Image/Build/RedBoot cp $(KDIR)/vmlinux.elf $(BIN_DIR)/openwrt-$(1)-vmlinux.elf gzip -9 -c $(KDIR)/vmlinux > $(KDIR)/vmlinux.bin.gz @@ -106,29 +108,29 @@ define Image/Build dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync # Various routers $(call Image/Build/CFE,$(1),96345GW2,6345,96345GW2-generic) - $(call Image/Build/CFE,$(1),96345GW2,6345,96348GW2-bc221,,-y 5) + $(call Image/Build/CFE,$(1),96345GW2,6345,96348GW2-bc221,,--layoutver 5) $(call Image/Build/CFE,$(1),96345GW2,6345,92345GW2-revision,OpenWRT-$(REVISION)) $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-generic,,) - $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-bc221,,-y 5) + $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-bc221,,--layoutver 5) $(call Image/Build/CFE,$(1),6338GW,6338,6338GW-generic,,) $(call Image/Build/CFE,$(1),6338W,6338,6338W-generic,,) # BT Voyager V210_BTR - $(call Image/Build/CFE,$(1),V210_BB,6348,BTV210_BTR,,-y 5) + $(call Image/Build/CFE,$(1),V210_BB,6348,BTV210_BTR,,--layoutver 5) # BT Voyager V210_ROI, V210_WB - $(call Image/Build/CFE,$(1),V210,6348,BTV210_ROI_WB,,-y 5) + $(call Image/Build/CFE,$(1),V210,6348,BTV210_ROI_WB,,--layoutver 5) # BT Voyager V2091_BTR - $(call Image/Build/CFE,$(1),V2091_BB,6348,BTV2091_BTR,,y 5) + $(call Image/Build/CFE,$(1),V2091_BB,6348,BTV2091_BTR,,--layoutver 5) # BT Voyager V2091_ROI, V2091_WB - $(call Image/Build/CFE,$(1),V2091,6348,BTV2091_ROI_WB,,-y 5) + $(call Image/Build/CFE,$(1),V2091,6348,BTV2091_ROI_WB,,--layoutver 5) # BT Voyager V220V, V220V_MGCP_BTR - $(call Image/Build/CFE,$(1),RTA1052V,6348,BTV220V_MGCP_BTR,,-y 5) + $(call Image/Build/CFE,$(1),RTA1052V,6348,BTV220V_MGCP_BTR,,--layoutver 5) # BT Voyager V2110, V2110_AA, V2110_ROI - $(call Image/Build/CFE,$(1),V2110,6348,BTV2110,,-y 5) + $(call Image/Build/CFE,$(1),V2110,6348,BTV2110,,--layoutver 5) # BT Voyager V2500V, V2500V_SIP_CLUB, V2500V_AA - $(call Image/Build/CFE,$(1),V2500V_BB,6348,BTV2500V,,-y 5) + $(call Image/Build/CFE,$(1),V2500V_BB,6348,BTV2500V,,--layoutver 5) # RTA1025W_16 (numerous routers) - $(call Image/Build/CFE,$(1),RTA1025W_16,6348,RTA1025W_16,,-y 5) + $(call Image/Build/CFE,$(1),RTA1025W_16,6348,RTA1025W_16,,--layoutver 5) # Tecom GW6000 $(call Image/Build/CFE,$(1),96348GW,6348,GW6000) # Tecom GW6200 @@ -166,7 +168,7 @@ define Image/Build # Pirelli A226G $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G-cfe) $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G) - + # RG100A,DB120 etc. $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,RG100A_DB120) diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index ace2aaae2..eb42f630f 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -15,7 +15,6 @@ define cc $(CC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/bin/$(firstword $(1)) $(foreach src,$(1),src/$(src).c) $(2) endef - define Host/Compile mkdir -p $(HOST_BUILD_DIR)/bin $(call cc,addpattern) @@ -33,7 +32,7 @@ define Host/Compile $(call cc,mkcasfw) $(call cc,mkfwimage,-lz) $(call cc,mkfwimage2,-lz) - $(call cc,imagetag) + $(call cc,imagetag imagetag_cmdline) $(call cc,add_header) $(call cc,makeamitbin) $(call cc,encode_crc) diff --git a/tools/firmware-utils/src/imagetag.c b/tools/firmware-utils/src/imagetag.c index 0ecbada28..1818daaca 100644 --- a/tools/firmware-utils/src/imagetag.c +++ b/tools/firmware-utils/src/imagetag.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 2008 Axel Gembe <ago@bastart.eu.org> - * Copyright (C) 2009 Daniel Dickinson <crazycshore@gmail.com> + * Copyright (C) 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> */ #include <stdio.h> @@ -17,25 +17,10 @@ #include <netinet/in.h> #include "bcm_tag.h" +#include "imagetag_cmdline.h" -#define IMAGETAG_MAGIC1 "Broadcom Corporatio" -#define IMAGETAG_MAGIC2 "ver. 2.0" -#define IMAGETAG_VER "6" -#define IMAGETAG_DEFAULT_LOADADDR 0x80010000 -#define DEFAULT_FW_OFFSET 0x10000 -#define DEFAULT_FLASH_START 0xBFC00000 -#define DEFAULT_FLASH_BS (64 * 1024) #define DEADCODE 0xDEADC0DE -union int2char { - uint32_t input; - char output[4]; -}; - -/* Convert uint32_t CRC to bigendian and copy it into a character array */ -#define int2tag(tag, value) intchar.input = htonl(value); \ - memcpy(tag, intchar.output, sizeof(union int2char)) - /* Kernel header */ struct kernelhdr { uint32_t loadaddr; /* Kernel load address */ @@ -80,6 +65,11 @@ static uint32_t crc32tab[256] = { 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; +void int2tag(char *tag, uint32_t value) { + uint32_t network = htonl(value); + memcpy(tag, (char *)(&network), 4); +} + uint32_t crc32(uint32_t crc, uint8_t *data, size_t len) { while (len--) @@ -126,38 +116,29 @@ size_t getlen(FILE *fp) return retval; } -int tagfile(const char *kernel, const char *rootfs, const char *bin, - const char *boardid, const char *chipid, const uint32_t fwaddr, - const uint32_t loadaddr, const uint32_t entry, - const char *ver, const char *magic2, const uint32_t flash_bs, - const char *rsignature, const char *layoutver) +int tagfile(const char *kernel, const char *rootfs, const char *bin, \ + const struct gengetopt_args_info *args, \ + uint32_t flash_start, uint32_t image_offset, \ + uint32_t block_size, uint32_t load_address, uint32_t entry) { struct bcm_tag tag; struct kernelhdr khdr; - FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile; - size_t kerneloff, kernellen, rootfsoff, rootfslen, read, imagelen, rootfsoffpadlen, kernelfslen; + FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile = NULL, *cfefile = NULL; + size_t cfeoff, cfelen, kerneloff, kernellen, rootfsoff, rootfslen, \ + read, imagelen, rootfsoffpadlen = 0, kernelfslen, kerneloffpadlen = 0, oldrootfslen; uint8_t readbuf[1024]; uint32_t imagecrc = IMAGETAG_CRC_START; uint32_t kernelcrc = IMAGETAG_CRC_START; uint32_t rootfscrc = IMAGETAG_CRC_START; uint32_t kernelfscrc = IMAGETAG_CRC_START; + uint32_t fwaddr = 0; + uint8_t crc_val; const uint32_t deadcode = htonl(DEADCODE); - union int2char intchar; - int i; - int is_pirelli = 0; - - memset(&tag, 0, sizeof(struct bcm_tag)); + int i; + int is_pirelli = 0; - if (strlen(boardid) >= sizeof(tag.boardid)) { - fprintf(stderr, "Board id is too long!\n"); - return 1; - } - /* Likewise chipid */ - if (strlen(chipid) >= sizeof(tag.chipid)) { - fprintf(stderr, "Chip id is too long!\n"); - return 1; - } + memset(&tag, 0, sizeof(struct bcm_tag)); if (!kernel || !rootfs) { fprintf(stderr, "imagetag can't create an image without both kernel and rootfs\n"); @@ -178,122 +159,253 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, return 1; } - /* Build the kernel address and length (doesn't need to be aligned, read only) */ - kerneloff = fwaddr + sizeof(tag); - kernellen = getlen(kernelfile); - - /* Build the kernel header */ - khdr.loadaddr = htonl(loadaddr); - khdr.entry = htonl(entry); - khdr.lzmalen = htonl(kernellen); + if ((args->cfe_given) && (args->cfe_arg)) { + if (!(cfefile = fopen(args->cfe_arg, "rb"))) { + fprintf(stderr, "Unable to open CFE file \"%s\"\n", args->cfe_arg); + } + } - /* Increase the kernel size by the header size */ - kernellen += sizeof(khdr); + fwaddr = flash_start + image_offset; + if (cfefile) { + cfeoff = flash_start; + cfelen = getlen(cfefile); + /* Seek to the start of the file after tag */ + fseek(binfile, sizeof(tag), SEEK_SET); + + /* Write the cfe */ + while (cfefile && !feof(cfefile) && !ferror(cfefile)) { + read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), cfefile); + fwrite(readbuf, sizeof(uint8_t), read, binfile); + } - /* Build the rootfs address and length (start and end do need to be aligned on flash erase block boundaries */ - rootfsoff = kerneloff + kernellen; - rootfsoff = (rootfsoff % flash_bs) > 0 ? (((rootfsoff / flash_bs) + 1) * flash_bs) : rootfsoff; - rootfslen = getlen(rootfsfile); - rootfslen = ( (rootfslen % flash_bs) > 0 ? (((rootfslen / flash_bs) + 1) * flash_bs) : rootfslen ); - imagelen = rootfsoff + rootfslen - kerneloff + sizeof(deadcode); - rootfsoffpadlen = rootfsoff - (kerneloff + kernellen); + } else { + cfeoff = 0; + cfelen = 0; + } - /* Seek to the start of the kernel */ - fseek(binfile, kerneloff - fwaddr, SEEK_SET); + if (!args->root_first_flag) { + /* Build the kernel address and length (doesn't need to be aligned, read only) */ + kerneloff = fwaddr + sizeof(tag); + + kernellen = getlen(kernelfile); + + if (!args->kernel_file_has_header_flag) { + /* Build the kernel header */ + khdr.loadaddr = htonl(load_address); + khdr.entry = htonl(entry); + khdr.lzmalen = htonl(kernellen); + + /* Increase the kernel size by the header size */ + kernellen += sizeof(khdr); + } + + /* Build the rootfs address and length (start and end do need to be aligned on flash erase block boundaries */ + rootfsoff = kerneloff + kernellen; + rootfsoff = (rootfsoff % block_size) > 0 ? (((rootfsoff / block_size) + 1) * block_size) : rootfsoff; + rootfslen = getlen(rootfsfile); + rootfslen = ( (rootfslen % block_size) > 0 ? (((rootfslen / block_size) + 1) * block_size) : rootfslen ); + imagelen = rootfsoff + rootfslen - kerneloff + sizeof(deadcode); + rootfsoffpadlen = rootfsoff - (kerneloff + kernellen); + + /* Seek to the start of the kernel */ + fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET); + + /* Write the kernel header */ + fwrite(&khdr, sizeof(khdr), 1, binfile); + + /* Write the kernel */ + while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) { + read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile); + fwrite(readbuf, sizeof(uint8_t), read, binfile); + } - /* Write the kernel header */ - fwrite(&khdr, sizeof(khdr), 1, binfile); + /* Write the RootFS */ + fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET); + while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) { + read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile); + fwrite(readbuf, sizeof(uint8_t), read, binfile); + } + + /* Align image to specified erase block size and append deadc0de */ + printf("Data alignment to %dk with 'deadc0de' appended\n", block_size/1024); + fseek(binfile, rootfsoff + rootfslen - fwaddr + cfelen, SEEK_SET); + fwrite(&deadcode, sizeof(uint32_t), 1, binfile); + + /* Flush the binfile buffer so that when we read from file, it contains + * everything in the buffer + */ + fflush(binfile); + + /* Compute the crc32 of the entire image (deadC0de included) */ + imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr + cfelen, imagelen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); + /* Compute the crc32 of the flashImageStart to rootLength. + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start to determine where to flash + * the image. Since we have the kernel first we have to give + * it the kernel address, but the crc uses the length + * associated with this address, which is added to the kernel + * length to determine the length of image to flash and thus + * needs to be rootfs + deadcode + */ + rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr + cfelen, rootfslen + sizeof(deadcode)); - /* Write the kernel */ - while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) { + } else { + /* Build the kernel address and length (doesn't need to be aligned, read only) */ + rootfsoff = fwaddr + sizeof(tag); + oldrootfslen = getlen(rootfsfile); + rootfslen = oldrootfslen; + rootfslen = ( (rootfslen % block_size) > 0 ? (((rootfslen / block_size) + 1) * block_size) : rootfslen ); + kerneloffpadlen = rootfslen - oldrootfslen; + + kerneloff = rootfsoff + rootfslen; + kernellen = getlen(kernelfile); + + imagelen = cfelen + rootfslen + kernellen; + + /* Seek to the start of the kernel */ + fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET); + + if (!args->kernel_file_has_header_flag) { + /* Build the kernel header */ + khdr.loadaddr = htonl(load_address); + khdr.entry = htonl(entry); + khdr.lzmalen = htonl(kernellen); + + /* Write the kernel header */ + fwrite(&khdr, sizeof(khdr), 1, binfile); + + /* Increase the kernel size by the header size */ + kernellen += sizeof(khdr); + } + + /* Write the kernel */ + while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); - } + } - /* Write the RootFS */ - fseek(binfile, rootfsoff - fwaddr, SEEK_SET); - while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) { + /* Write the RootFS */ + fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET); + while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); + } + + /* Flush the binfile buffer so that when we read from file, it contains + * everything in the buffer + */ + fflush(binfile); + + /* Compute the crc32 of the entire image (deadC0de included) */ + imagecrc = compute_crc32(imagecrc, binfile, sizeof(tag), imagelen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen); + kernelfscrc = compute_crc32(kernelfscrc, binfile, rootfsoff - fwaddr + cfelen, kernellen + rootfslen); + rootfscrc = compute_crc32(rootfscrc, binfile, rootfsoff - fwaddr + cfelen, rootfslen); } - /* Align image to specified erase block size and append deadc0de */ - printf("Data alignment to %dk with 'deadc0de' appended\n", flash_bs/1024); - fseek(binfile, rootfsoff + rootfslen - fwaddr, SEEK_SET); - fwrite(&deadcode, sizeof(uint32_t), 1, binfile); - - /* Flush the binfile buffer so that when we read from file, it contains - * everything in the buffer - */ - fflush(binfile); - - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); - /* Compute the crc32 of the flashImageStart to rootLength. - * The broadcom firmware assumes the rootfs starts the image, - * therefore uses the rootfs start to determine where to flash - * the image. Since we have the kernel first we have to give - * it the kernel address, but the crc uses the length - * associated with this address, which is added to the kernel - * length to determine the length of image to flash and thus - * needs to be rootfs + deadcode - */ - rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode)); - /* Close the files */ + if (cfefile) { + fclose(cfefile); + } fclose(kernelfile); fclose(rootfsfile); /* Build the tag */ - strncpy(tag.tagVersion, ver, TAGVER_LEN); - strncpy(tag.sig_1, IMAGETAG_MAGIC1, sizeof(tag.sig_1) - 1); - strncpy(tag.sig_2, magic2, sizeof(tag.sig_2) - 1); - strcpy(tag.chipid, chipid); - strcpy(tag.boardid, boardid); + strncpy(tag.tagVersion, args->tag_version_arg, sizeof(tag.tagVersion) - 1); + strncpy(tag.sig_1, args->signature_arg, sizeof(tag.sig_1) - 1); + strncpy(tag.sig_2, args->signature2_arg, sizeof(tag.sig_2) - 1); + strncpy(tag.chipid, args->chipid_arg, sizeof(tag.chipid) - 1); + strncpy(tag.boardid, args->boardid_arg, sizeof(tag.boardid) - 1); strcpy(tag.big_endian, "1"); sprintf(tag.totalLength, "%lu", imagelen); - /* We don't include CFE */ - strcpy(tag.cfeAddress, "0"); - strcpy(tag.cfeLength, "0"); + if (args->cfe_given) { + sprintf(tag.cfeAddress, "%lu", flash_start); + sprintf(tag.cfeLength, "%lu", cfelen); + } else { + /* We don't include CFE */ + strcpy(tag.cfeAddress, "0"); + strcpy(tag.cfeLength, "0"); + } - sprintf(tag.kernelAddress, "%lu", kerneloff); + sprintf(tag.kernelAddress, "%lu", kerneloff); sprintf(tag.kernelLength, "%lu", kernellen + rootfsoffpadlen); - sprintf(tag.flashImageStart, "%lu", kerneloff); - sprintf(tag.rootLength, "%lu", rootfslen + sizeof(deadcode)); - if (rsignature) { - strncpy(tag.rsa_signature, rsignature, RSASIG_LEN); + if (args->root_first_flag) { + sprintf(tag.flashImageStart, "%lu", rootfsoff); + sprintf(tag.rootLength, "%lu", rootfslen); + } else { + sprintf(tag.flashImageStart, "%lu", kerneloff); + sprintf(tag.rootLength, "%lu", rootfslen + sizeof(deadcode)); + } + + if (args->rsa_signature_given) { + strncpy(tag.rsa_signature, args->rsa_signature_arg, RSASIG_LEN); + } + + if (args->layoutver_given) { + strncpy(tag.flashLayoutVer, args->layoutver_arg, TAGLAYOUT_LEN); } - if (layoutver) { - strncpy(tag.flashLayoutVer, layoutver, TAGLAYOUT_LEN); + if (args->info1_given) { + strncpy(tag.information1, args->info1_arg, TAGINFO1_LEN); + } + + if (args->info2_given) { + strncpy(tag.information2, args->info2_arg, TAGINFO2_LEN); + } + + if (args->reserved1_given) { + strncpy(tag.reserved1, args->reserved1_arg, 8); + } + + if (args->reserved2_given) { + strncpy(tag.reserved2, args->reserved2_arg, 16); + } + + if (args->altinfo_given) { + strncpy(&tag.information1[0], args->altinfo_arg, ALTTAGINFO_LEN); + } + + if (args->second_image_flag_given) { + if (strncmp(args->second_image_flag_arg, "2", DUALFLAG_LEN) != 0) { + strncpy(tag.dualImage, args->second_image_flag_arg, DUALFLAG_LEN); + } + } + + if (args->inactive_given) { + if (strncmp(args->inactive_arg, "2", INACTIVEFLAG_LEN) != 0) { + strncpy(tag.inactiveFlag, args->second_image_flag_arg, INACTIVEFLAG_LEN); + } } for (i = 0; i < NUM_PIRELLI; i++) { - if (strncmp(boardid, pirellitab[i], BOARDID_LEN) == 0) { + if (strncmp(args->boardid_arg, pirellitab[i], BOARDID_LEN) == 0) { is_pirelli = 1; break; } } if ( !is_pirelli ) { - int2tag(tag.imageCRC, imagecrc); + int2tag(tag.imageCRC, kernelfscrc); } else { - int2tag(tag.imageCRC, kernelcrc); + int2tag(tag.imageCRC, kernelcrc); } - int2tag(tag.kernelCRC, kernelcrc); - int2tag(tag.rootfsCRC, rootfscrc); + + int2tag(&(tag.rootfsCRC[0]), rootfscrc); + int2tag(tag.kernelCRC, kernelcrc); int2tag(tag.fskernelCRC, kernelfscrc); int2tag(tag.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); fseek(binfile, 0L, SEEK_SET); fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile); + fflush(binfile); fclose(binfile); return 0; @@ -301,122 +413,93 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, int main(int argc, char **argv) { - int c, i; - char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *rsignature, *layoutver; - uint32_t flashstart, fwoffset, loadaddr, entry; - uint32_t fwaddr, flash_bs; - int tagidfound = 0; + int c, i; + char *kernel, *rootfs, *bin; + uint32_t flash_start, image_offset, block_size, load_address, entry; + flash_start = image_offset = block_size = load_address = entry = 0; + struct gengetopt_args_info parsed_args; - kernel = rootfs = bin = boardid = chipid = magic2 = ver = rsignature = layoutver = NULL; - entry = 0; + kernel = rootfs = bin = NULL; - flashstart = DEFAULT_FLASH_START; - fwoffset = DEFAULT_FW_OFFSET; - loadaddr = IMAGETAG_DEFAULT_LOADADDR; - flash_bs = DEFAULT_FLASH_BS; + if (cmdline_parser(argc, argv, &parsed_args)) { + exit(1); + } - printf("Broadcom image tagger - v1.0.0\n"); + printf("Broadcom 63xx image tagger - v2.0.0\n"); printf("Copyright (C) 2008 Axel Gembe\n"); printf("Copyright (C) 2009-2010 Daniel Dickinson\n"); - - while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:r:y:")) != -1) { - switch (c) { - case 'i': - kernel = optarg; - break; - case 'f': - rootfs = optarg; - break; - case 'o': - bin = optarg; - break; - case 'b': - boardid = optarg; - break; - case 'c': - chipid = optarg; - break; - case 's': - flashstart = strtoul(optarg, NULL, 16); - break; - case 'n': - fwoffset = strtoul(optarg, NULL, 16); - break; - case 'v': - ver = optarg; - break; - case 'm': - magic2 = optarg; - break; - case 'k': - flash_bs = strtoul(optarg, NULL, 16); - break; - case 'l': - loadaddr = strtoul(optarg, NULL, 16); - break; - case 'e': - entry = strtoul(optarg, NULL, 16); - break; - case 'r': - rsignature = optarg; - break; - case 'y': - layoutver = optarg; - break; - case 'h': - default: - fprintf(stderr, "Usage: imagetag <parameters>\n\n"); - fprintf(stderr, " -i <kernel> - The LZMA compressed kernel file to include in the image\n"); - fprintf(stderr, " -f <rootfs> - The RootFS file to include in the image\n"); - fprintf(stderr, " -o <bin> - The output file\n"); - fprintf(stderr, " -b <boardid> - The board id to set in the image (i.e. \"96345GW2\")\n"); - fprintf(stderr, " -c <chipid> - The chip id to set in the image (i.e. \"6345\")\n"); - fprintf(stderr, " -s <flashstart> - Flash start address (i.e. \"0xBFC00000\"\n"); - fprintf(stderr, " -n <fwoffset> - \n"); - fprintf(stderr, " -v <version> - \n"); - fprintf(stderr, " -m <magic2> - \n"); - fprintf(stderr, " -k <flash_bs> - flash erase block size\n"); - fprintf(stderr, " -l <loadaddr> - Address where the kernel expects to be loaded (defaults to 0x80010000)\n"); - fprintf(stderr, " -e <entry> - Address where the kernel entry point will end up\n"); - fprintf(stderr, " -r <signature> - vendor specific signature, for those that need it"); - fprintf(stderr, " -y <layoutver> - Flash Layout Version (2.2x code versions need this)"); - fprintf(stderr, " -h - Displays this text\n\n"); - return 1; - } + printf("Licensed under the terms of the Gnu General Public License\n"); + + kernel = parsed_args.kernel_arg; + rootfs = parsed_args.rootfs_arg; + bin = parsed_args.output_arg; + if (strlen(parsed_args.tag_version_arg) >= TAGVER_LEN) { + fprintf(stderr, "Error: Tag Version (tag_version,v) too long.\n"); + exit(1); } - - if (!boardid || !chipid) { - fprintf(stderr, "You need to specify the board (-b) and chip id (-c)!\n"); - return 1; + if (strlen(parsed_args.boardid_arg) >= BOARDID_LEN) { + fprintf(stderr, "Error: Board ID (boardid,b) too long.\n"); + exit(1); } - - if (entry == 0) { - fprintf(stderr, "You need to specify the kernel entry (-e)\n"); - return 1; + if (strlen(parsed_args.chipid_arg) >= CHIPID_LEN) { + fprintf(stderr, "Error: Chip ID (chipid,c) too long.\n"); + exit(1); } - - /* Fallback to defaults */ - - fwaddr = flashstart + fwoffset; - - if (!magic2) { - magic2 = malloc(sizeof(char) * 14); - if (!magic2) { - perror("malloc"); - return 1; - } - strcpy(magic2, IMAGETAG_MAGIC2); + if (strlen(parsed_args.signature_arg) >= SIG1_LEN) { + fprintf(stderr, "Error: Magic string (signature,a) too long.\n"); + exit(1); + } + if (strlen(parsed_args.signature2_arg) >= SIG2_LEN) { + fprintf(stderr, "Error: Second magic string (signature2,m) too long.\n"); + exit(1); + } + if (parsed_args.layoutver_given) { + if (strlen(parsed_args.layoutver_arg) > FLASHLAYOUTVER_LEN) { + fprintf(stderr, "Error: Flash layout version (layoutver,y) too long.\n"); + exit(1); + } + } + if (parsed_args.rsa_signature_given) { + if (strlen(parsed_args.rsa_signature_arg) > RSASIG_LEN) { + fprintf(stderr, "Error: RSA Signature (rsa_signature,r) too long.\n"); + exit(1); + } } - if (!ver) { - ver = malloc(sizeof(char) * 4); - if (!ver) { - perror("malloc"); - return 1; - } - strcpy(ver, IMAGETAG_VER); + if (parsed_args.info1_given) { + if (strlen(parsed_args.info1_arg) >= TAGINFO1_LEN) { + fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n"); + exit(1); + } } + if (parsed_args.info2_given) { + if (strlen(parsed_args.info2_arg) >= TAGINFO2_LEN) { + fprintf(stderr, "Error: Vendor Information 2 (info2) too long.\n"); + exit(1); + } + } - return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, rsignature, layoutver); + if (parsed_args.altinfo_given) { + if (strlen(parsed_args.altinfo_arg) >= ALTTAGINFO_LEN) { + fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n"); + exit(1); + } + } + flash_start = strtoul(parsed_args.flash_start_arg, NULL, 16); + image_offset = strtoul(parsed_args.image_offset_arg, NULL, 16); + block_size = strtoul(parsed_args.block_size_arg, NULL, 16); + + if (!parsed_args.kernel_file_has_header_flag) { + load_address = strtoul(parsed_args.load_addr_arg, NULL, 16); + entry = strtoul(parsed_args.entry_arg, NULL, 16); + if (load_address == 0) { + fprintf(stderr, "Error: Invalid value for load address\n"); + } + if (entry == 0) { + fprintf(stderr, "Error: Invalid value for entry\n"); + } + } + + return tagfile(kernel, rootfs, bin, &parsed_args, flash_start, image_offset, block_size, load_address, entry); } diff --git a/tools/firmware-utils/src/imagetag.ggo b/tools/firmware-utils/src/imagetag.ggo new file mode 100644 index 000000000..4b9d5d361 --- /dev/null +++ b/tools/firmware-utils/src/imagetag.ggo @@ -0,0 +1,45 @@ +# Command line option parsing generator file for imagetag +# Supplied-To: gengetopt +# +# Copyright 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# + +package "imagetag" +version "2.0.0" +purpose "Generate image with CFE imagetag for Broadcom 63xx routers." +description "Copyright (C) 2008 Axel Gembe +Copyright (C) 2009-2010 Daniel Dickinson +Licensed unter the terms of the Gnu General Public License. + +Given a root filesystem, a linux kernel, and an optional CFE, generates an image with an imagetag for a Broadcom 63xx-based router. Additional parameters to be specified depend on the specfic brand and model of router." +args "--file-name=imagetag_cmdline" + +option "kernel" i "File with LZMA compressed kernel to include in the image." string typestr="filename" required +option "rootfs" f "File with RootFS to include in the image." string typestr="filename" required +option "output" o "Name of output file." string typestr="filename" required +option "cfe" - "File with CFE to include in the image." string typestr="filename" optional +option "boardid" b "Board ID to set in the image (must match what router expects, e.g. \"96345GW2\")." string required +option "chipid" c "Chip ID to set in the image (must match the actual hardware, e.g. \"6345\")." string required +option "flash-start" s "Flash start address." string typestr="address" optional default="0xBFC00000" +option "image-offset" n "Offset from start address for the first byte after the CFE (in memory)." string typestr="offset" default="0x10000" optional +option "tag-version" v "Version number for imagetag format." string default="6" optional +option "signature" a "Magic string (signature), for boards that need it." string default="Broadcom Corporatio" optional +option "signature2" m "Second magic string (signature2)." string default="ver. 2.0" optional +option "block-size" k "Flash erase block size." string optional default="0x10000" +option "load-addr" l "Kernel load address." string typestr="address" required +option "entry" e "Address where the kernel entry point will be for booting." string typestr="address" required +option "layoutver" y "Flash layout version (version 2.2x of the Broadcom code requires this)." string optional +option "info1" 1 "String for first vendor information section." string optional +option "altinfo" - "String for vendor information section (alternate/pirelli)." string optional +option "info2" 2 "String for second vendor information section." string optional +option "root-first" - "Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory)." flag off +option "rsa-signature" r "String for RSA Signature section." string optional +option "second-image-flag" - "Dual Image Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional +option "inactive" - "Inactive Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional +option "reserved1" - "String for first reserved section." string optional +option "reserved2" - "String for second reserved section." string optional +option "kernel-file-has-header" - "Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed" flag off diff --git a/tools/firmware-utils/src/imagetag_cmdline.c b/tools/firmware-utils/src/imagetag_cmdline.c new file mode 100644 index 000000000..85f214bc6 --- /dev/null +++ b/tools/firmware-utils/src/imagetag_cmdline.c @@ -0,0 +1,1163 @@ +/* + File autogenerated by gengetopt version 2.22.4 + generated with the following command: + gengetopt --file-name=imagetag_cmdline --file-name=imagetag_cmdline + + The developers of gengetopt consider the fixed text that goes in all + gengetopt output files to be in the public domain: + we make no copyright claims on it. +*/ + +/* If we use autoconf. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef FIX_UNUSED +#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ +#endif + +#include <getopt.h> + +#include "imagetag_cmdline.h" + +const char *gengetopt_args_info_purpose = "Generate image with CFE imagetag for Broadcom 63xx routers."; + +const char *gengetopt_args_info_usage = "Usage: imagetag [OPTIONS]..."; + +const char *gengetopt_args_info_description = "Copyright (C) 2008 Axel Gembe\nCopyright (C) 2009-2010 Daniel Dickinson\nLicensed unter the terms of the Gnu General Public License.\n\nGiven a root filesystem, a linux kernel, and an optional CFE, generates an \nimage with an imagetag for a Broadcom 63xx-based router. Additional parameters \nto be specified depend on the specfic brand and model of router."; + +const char *gengetopt_args_info_help[] = { + " -h, --help Print help and exit", + " -V, --version Print version and exit", + " -i, --kernel=filename File with LZMA compressed kernel to include in \n the image.", + " -f, --rootfs=filename File with RootFS to include in the image.", + " -o, --output=filename Name of output file.", + " --cfe=filename File with CFE to include in the image.", + " -b, --boardid=STRING Board ID to set in the image (must match what \n router expects, e.g. \"96345GW2\").", + " -c, --chipid=STRING Chip ID to set in the image (must match the \n actual hardware, e.g. \"6345\").", + " -s, --flash-start=address Flash start address. (default=`0xBFC00000')", + " -n, --image-offset=offset Offset from start address for the first byte \n after the CFE (in memory). \n (default=`0x10000')", + " -v, --tag-version=STRING Version number for imagetag format. \n (default=`6')", + " -a, --signature=STRING Magic string (signature), for boards that need \n it. (default=`Broadcom Corporatio')", + " -m, --signature2=STRING Second magic string (signature2). \n (default=`ver. 2.0')", + " -k, --block-size=STRING Flash erase block size. (default=`0x10000')", + " -l, --load-addr=address Kernel load address.", + " -e, --entry=address Address where the kernel entry point will be \n for booting.", + " -y, --layoutver=STRING Flash layout version (version 2.2x of the \n Broadcom code requires this).", + " -1, --info1=STRING String for first vendor information section.", + " --altinfo=STRING String for vendor information section \n (alternate/pirelli).", + " -2, --info2=STRING String for second vendor information section.", + " --root-first Put the rootfs before the kernel (only for \n stock images, e.g. captured from the router's \n flash memory). (default=off)", + " -r, --rsa-signature=STRING String for RSA Signature section.", + " --second-image-flag=flag-value\n Dual Image Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')", + " --inactive=flag-value Inactive Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')", + " --reserved1=STRING String for first reserved section.", + " --reserved2=STRING String for second reserved section.", + " --kernel-file-has-header Indicates that the kernel file includes the \n kernel header with correct load address and \n entry point, so no changes are needed \n (default=off)", + 0 +}; + +typedef enum {ARG_NO + , ARG_FLAG + , ARG_STRING +} cmdline_parser_arg_type; + +static +void clear_given (struct gengetopt_args_info *args_info); +static +void clear_args (struct gengetopt_args_info *args_info); + +static int +cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, + struct cmdline_parser_params *params, const char *additional_error); + +static int +cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); + +const char *cmdline_parser_second_image_flag_values[] = {"0", "1", "2", 0}; /*< Possible values for second-image-flag. */ +const char *cmdline_parser_inactive_values[] = {"0", "1", "2", 0}; /*< Possible values for inactive. */ + +static char * +gengetopt_strdup (const char *s); + +static +void clear_given (struct gengetopt_args_info *args_info) +{ + args_info->help_given = 0 ; + args_info->version_given = 0 ; + args_info->kernel_given = 0 ; + args_info->rootfs_given = 0 ; + args_info->output_given = 0 ; + args_info->cfe_given = 0 ; + args_info->boardid_given = 0 ; + args_info->chipid_given = 0 ; + args_info->flash_start_given = 0 ; + args_info->image_offset_given = 0 ; + args_info->tag_version_given = 0 ; + args_info->signature_given = 0 ; + args_info->signature2_given = 0 ; + args_info->block_size_given = 0 ; + args_info->load_addr_given = 0 ; + args_info->entry_given = 0 ; + args_info->layoutver_given = 0 ; + args_info->info1_given = 0 ; + args_info->altinfo_given = 0 ; + args_info->info2_given = 0 ; + args_info->root_first_given = 0 ; + args_info->rsa_signature_given = 0 ; + args_info->second_image_flag_given = 0 ; + args_info->inactive_given = 0 ; + args_info->reserved1_given = 0 ; + args_info->reserved2_given = 0 ; + args_info->kernel_file_has_header_given = 0 ; +} + +static +void clear_args (struct gengetopt_args_info *args_info) +{ + FIX_UNUSED (args_info); + args_info->kernel_arg = NULL; + args_info->kernel_orig = NULL; + args_info->rootfs_arg = NULL; + args_info->rootfs_orig = NULL; + args_info->output_arg = NULL; + args_info->output_orig = NULL; + args_info->cfe_arg = NULL; + args_info->cfe_orig = NULL; + args_info->boardid_arg = NULL; + args_info->boardid_orig = NULL; + args_info->chipid_arg = NULL; + args_info->chipid_orig = NULL; + args_info->flash_start_arg = gengetopt_strdup ("0xBFC00000"); + args_info->flash_start_orig = NULL; + args_info->image_offset_arg = gengetopt_strdup ("0x10000"); + args_info->image_offset_orig = NULL; + args_info->tag_version_arg = gengetopt_strdup ("6"); + args_info->tag_version_orig = NULL; + args_info->signature_arg = gengetopt_strdup ("Broadcom Corporatio"); + args_info->signature_orig = NULL; + args_info->signature2_arg = gengetopt_strdup ("ver. 2.0"); + args_info->signature2_orig = NULL; + args_info->block_size_arg = gengetopt_strdup ("0x10000"); + args_info->block_size_orig = NULL; + args_info->load_addr_arg = NULL; + args_info->load_addr_orig = NULL; + args_info->entry_arg = NULL; + args_info->entry_orig = NULL; + args_info->layoutver_arg = NULL; + args_info->layoutver_orig = NULL; + args_info->info1_arg = NULL; + args_info->info1_orig = NULL; + args_info->altinfo_arg = NULL; + args_info->altinfo_orig = NULL; + args_info->info2_arg = NULL; + args_info->info2_orig = NULL; + args_info->root_first_flag = 0; + args_info->rsa_signature_arg = NULL; + args_info->rsa_signature_orig = NULL; + args_info->second_image_flag_arg = gengetopt_strdup ("2"); + args_info->second_image_flag_orig = NULL; + args_info->inactive_arg = gengetopt_strdup ("2"); + args_info->inactive_orig = NULL; + args_info->reserved1_arg = NULL; + args_info->reserved1_orig = NULL; + args_info->reserved2_arg = NULL; + args_info->reserved2_orig = NULL; + args_info->kernel_file_has_header_flag = 0; + +} + +static +void init_args_info(struct gengetopt_args_info *args_info) +{ + + + args_info->help_help = gengetopt_args_info_help[0] ; + args_info->version_help = gengetopt_args_info_help[1] ; + args_info->kernel_help = gengetopt_args_info_help[2] ; + args_info->rootfs_help = gengetopt_args_info_help[3] ; + args_info->output_help = gengetopt_args_info_help[4] ; + args_info->cfe_help = gengetopt_args_info_help[5] ; + args_info->boardid_help = gengetopt_args_info_help[6] ; + args_info->chipid_help = gengetopt_args_info_help[7] ; + args_info->flash_start_help = gengetopt_args_info_help[8] ; + args_info->image_offset_help = gengetopt_args_info_help[9] ; + args_info->tag_version_help = gengetopt_args_info_help[10] ; + args_info->signature_help = gengetopt_args_info_help[11] ; + args_info->signature2_help = gengetopt_args_info_help[12] ; + args_info->block_size_help = gengetopt_args_info_help[13] ; + args_info->load_addr_help = gengetopt_args_info_help[14] ; + args_info->entry_help = gengetopt_args_info_help[15] ; + args_info->layoutver_help = gengetopt_args_info_help[16] ; + args_info->info1_help = gengetopt_args_info_help[17] ; + args_info->altinfo_help = gengetopt_args_info_help[18] ; + args_info->info2_help = gengetopt_args_info_help[19] ; + args_info->root_first_help = gengetopt_args_info_help[20] ; + args_info->rsa_signature_help = gengetopt_args_info_help[21] ; + args_info->second_image_flag_help = gengetopt_args_info_help[22] ; + args_info->inactive_help = gengetopt_args_info_help[23] ; + args_info->reserved1_help = gengetopt_args_info_help[24] ; + args_info->reserved2_help = gengetopt_args_info_help[25] ; + args_info->kernel_file_has_header_help = gengetopt_args_info_help[26] ; + +} + +void +cmdline_parser_print_version (void) +{ + printf ("%s %s\n", + (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), + CMDLINE_PARSER_VERSION); +} + +static void print_help_common(void) { + cmdline_parser_print_version (); + + if (strlen(gengetopt_args_info_purpose) > 0) + printf("\n%s\n", gengetopt_args_info_purpose); + + if (strlen(gengetopt_args_info_usage) > 0) + printf("\n%s\n", gengetopt_args_info_usage); + + printf("\n"); + + if (strlen(gengetopt_args_info_description) > 0) + printf("%s\n\n", gengetopt_args_info_description); +} + +void +cmdline_parser_print_help (void) +{ + int i = 0; + print_help_common(); + while (gengetopt_args_info_help[i]) + printf("%s\n", gengetopt_args_info_help[i++]); +} + +void +cmdline_parser_init (struct gengetopt_args_info *args_info) +{ + clear_given (args_info); + clear_args (args_info); + init_args_info (args_info); +} + +void +cmdline_parser_params_init(struct cmdline_parser_params *params) +{ + if (params) + { + params->override = 0; + params->initialize = 1; + params->check_required = 1; + params->check_ambiguity = 0; + params->print_errors = 1; + } +} + +struct cmdline_parser_params * +cmdline_parser_params_create(void) +{ + struct cmdline_parser_params *params = + (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); + cmdline_parser_params_init(params); + return params; +} + +static void +free_string_field (char **s) +{ + if (*s) + { + free (*s); + *s = 0; + } +} + + +static void +cmdline_parser_release (struct gengetopt_args_info *args_info) +{ + + free_string_field (&(args_info->kernel_arg)); + free_string_field (&(args_info->kernel_orig)); + free_string_field (&(args_info->rootfs_arg)); + free_string_field (&(args_info->rootfs_orig)); + free_string_field (&(args_info->output_arg)); + free_string_field (&(args_info->output_orig)); + free_string_field (&(args_info->cfe_arg)); + free_string_field (&(args_info->cfe_orig)); + free_string_field (&(args_info->boardid_arg)); + free_string_field (&(args_info->boardid_orig)); + free_string_field (&(args_info->chipid_arg)); + free_string_field (&(args_info->chipid_orig)); + free_string_field (&(args_info->flash_start_arg)); + free_string_field (&(args_info->flash_start_orig)); + free_string_field (&(args_info->image_offset_arg)); + free_string_field (&(args_info->image_offset_orig)); + free_string_field (&(args_info->tag_version_arg)); + free_string_field (&(args_info->tag_version_orig)); + free_string_field (&(args_info->signature_arg)); + free_string_field (&(args_info->signature_orig)); + free_string_field (&(args_info->signature2_arg)); + free_string_field (&(args_info->signature2_orig)); + free_string_field (&(args_info->block_size_arg)); + free_string_field (&(args_info->block_size_orig)); + free_string_field (&(args_info->load_addr_arg)); + free_string_field (&(args_info->load_addr_orig)); + free_string_field (&(args_info->entry_arg)); + free_string_field (&(args_info->entry_orig)); + free_string_field (&(args_info->layoutver_arg)); + free_string_field (&(args_info->layoutver_orig)); + free_string_field (&(args_info->info1_arg)); + free_string_field (&(args_info->info1_orig)); + free_string_field (&(args_info->altinfo_arg)); + free_string_field (&(args_info->altinfo_orig)); + free_string_field (&(args_info->info2_arg)); + free_string_field (&(args_info->info2_orig)); + free_string_field (&(args_info->rsa_signature_arg)); + free_string_field (&(args_info->rsa_signature_orig)); + free_string_field (&(args_info->second_image_flag_arg)); + free_string_field (&(args_info->second_image_flag_orig)); + free_string_field (&(args_info->inactive_arg)); + free_string_field (&(args_info->inactive_orig)); + free_string_field (&(args_info->reserved1_arg)); + free_string_field (&(args_info->reserved1_orig)); + free_string_field (&(args_info->reserved2_arg)); + free_string_field (&(args_info->reserved2_orig)); + + + + clear_given (args_info); +} + +/** + * @param val the value to check + * @param values the possible values + * @return the index of the matched value: + * -1 if no value matched, + * -2 if more than one value has matched + */ +static int +check_possible_values(const char *val, const char *values[]) +{ + int i, found, last; + size_t len; + + if (!val) /* otherwise strlen() crashes below */ + return -1; /* -1 means no argument for the option */ + + found = last = 0; + + for (i = 0, len = strlen(val); values[i]; ++i) + { + if (strncmp(val, values[i], len) == 0) + { + ++found; + last = i; + if (strlen(values[i]) == len) + return i; /* exact macth no need to check more */ + } + } + + if (found == 1) /* one match: OK */ + return last; + + return (found ? -2 : -1); /* return many values or none matched */ +} + + +static void +write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) +{ + int found = -1; + if (arg) { + if (values) { + found = check_possible_values(arg, values); + } + if (found >= 0) + fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]); + else + fprintf(outfile, "%s=\"%s\"\n", opt, arg); + } else { + fprintf(outfile, "%s\n", opt); + } +} + + +int +cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) +{ + int i = 0; + + if (!outfile) + { + fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); + return EXIT_FAILURE; + } + + if (args_info->help_given) + write_into_file(outfile, "help", 0, 0 ); + if (args_info->version_given) + write_into_file(outfile, "version", 0, 0 ); + if (args_info->kernel_given) + write_into_file(outfile, "kernel", args_info->kernel_orig, 0); + if (args_info->rootfs_given) + write_into_file(outfile, "rootfs", args_info->rootfs_orig, 0); + if (args_info->output_given) + write_into_file(outfile, "output", args_info->output_orig, 0); + if (args_info->cfe_given) + write_into_file(outfile, "cfe", args_info->cfe_orig, 0); + if (args_info->boardid_given) + write_into_file(outfile, "boardid", args_info->boardid_orig, 0); + if (args_info->chipid_given) + write_into_file(outfile, "chipid", args_info->chipid_orig, 0); + if (args_info->flash_start_given) + write_into_file(outfile, "flash-start", args_info->flash_start_orig, 0); + if (args_info->image_offset_given) + write_into_file(outfile, "image-offset", args_info->image_offset_orig, 0); + if (args_info->tag_version_given) + write_into_file(outfile, "tag-version", args_info->tag_version_orig, 0); + if (args_info->signature_given) + write_into_file(outfile, "signature", args_info->signature_orig, 0); + if (args_info->signature2_given) + write_into_file(outfile, "signature2", args_info->signature2_orig, 0); + if (args_info->block_size_given) + write_into_file(outfile, "block-size", args_info->block_size_orig, 0); + if (args_info->load_addr_given) + write_into_file(outfile, "load-addr", args_info->load_addr_orig, 0); + if (args_info->entry_given) + write_into_file(outfile, "entry", args_info->entry_orig, 0); + if (args_info->layoutver_given) + write_into_file(outfile, "layoutver", args_info->layoutver_orig, 0); + if (args_info->info1_given) + write_into_file(outfile, "info1", args_info->info1_orig, 0); + if (args_info->altinfo_given) + write_into_file(outfile, "altinfo", args_info->altinfo_orig, 0); + if (args_info->info2_given) + write_into_file(outfile, "info2", args_info->info2_orig, 0); + if (args_info->root_first_given) + write_into_file(outfile, "root-first", 0, 0 ); + if (args_info->rsa_signature_given) + write_into_file(outfile, "rsa-signature", args_info->rsa_signature_orig, 0); + if (args_info->second_image_flag_given) + write_into_file(outfile, "second-image-flag", args_info->second_image_flag_orig, cmdline_parser_second_image_flag_values); + if (args_info->inactive_given) + write_into_file(outfile, "inactive", args_info->inactive_orig, cmdline_parser_inactive_values); + if (args_info->reserved1_given) + write_into_file(outfile, "reserved1", args_info->reserved1_orig, 0); + if (args_info->reserved2_given) + write_into_file(outfile, "reserved2", args_info->reserved2_orig, 0); + if (args_info->kernel_file_has_header_given) + write_into_file(outfile, "kernel-file-has-header", 0, 0 ); + + + i = EXIT_SUCCESS; + return i; +} + +int +cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) +{ + FILE *outfile; + int i = 0; + + outfile = fopen(filename, "w"); + + if (!outfile) + { + fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); + return EXIT_FAILURE; + } + + i = cmdline_parser_dump(outfile, args_info); + fclose (outfile); + + return i; +} + +void +cmdline_parser_free (struct gengetopt_args_info *args_info) +{ + cmdline_parser_release (args_info); +} + +/** @brief replacement of strdup, which is not standard */ +char * +gengetopt_strdup (const char *s) +{ + char *result = 0; + if (!s) + return result; + + result = (char*)malloc(strlen(s) + 1); + if (result == (char*)0) + return (char*)0; + strcpy(result, s); + return result; +} + +int +cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) +{ + return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); +} + +int +cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, + struct cmdline_parser_params *params) +{ + int result; + result = cmdline_parser_internal (argc, argv, args_info, params, 0); + + if (result == EXIT_FAILURE) + { + cmdline_parser_free (args_info); + exit (EXIT_FAILURE); + } + + return result; +} + +int +cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) +{ + int result; + struct cmdline_parser_params params; + + params.override = override; + params.initialize = initialize; + params.check_required = check_required; + params.check_ambiguity = 0; + params.print_errors = 1; + + result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); + + if (result == EXIT_FAILURE) + { + cmdline_parser_free (args_info); + exit (EXIT_FAILURE); + } + + return result; +} + +int +cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) +{ + int result = EXIT_SUCCESS; + + if (cmdline_parser_required2(args_info, prog_name, 0) > 0) + result = EXIT_FAILURE; + + if (result == EXIT_FAILURE) + { + cmdline_parser_free (args_info); + exit (EXIT_FAILURE); + } + + return result; +} + +int +cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) +{ + int error = 0; + FIX_UNUSED (additional_error); + + /* checks for required options */ + if (! args_info->kernel_given) + { + fprintf (stderr, "%s: '--kernel' ('-i') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->rootfs_given) + { + fprintf (stderr, "%s: '--rootfs' ('-f') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->output_given) + { + fprintf (stderr, "%s: '--output' ('-o') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->boardid_given) + { + fprintf (stderr, "%s: '--boardid' ('-b') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->chipid_given) + { + fprintf (stderr, "%s: '--chipid' ('-c') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->load_addr_given) + { + fprintf (stderr, "%s: '--load-addr' ('-l') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + if (! args_info->entry_given) + { + fprintf (stderr, "%s: '--entry' ('-e') option required%s\n", prog_name, (additional_error ? additional_error : "")); + error = 1; + } + + + /* checks for dependences among options */ + + return error; +} + + +static char *package_name = 0; + +/** + * @brief updates an option + * @param field the generic pointer to the field to update + * @param orig_field the pointer to the orig field + * @param field_given the pointer to the number of occurrence of this option + * @param prev_given the pointer to the number of occurrence already seen + * @param value the argument for this option (if null no arg was specified) + * @param possible_values the possible values for this option (if specified) + * @param default_value the default value (in case the option only accepts fixed values) + * @param arg_type the type of this option + * @param check_ambiguity @see cmdline_parser_params.check_ambiguity + * @param override @see cmdline_parser_params.override + * @param no_free whether to free a possible previous value + * @param multiple_option whether this is a multiple option + * @param long_opt the corresponding long option + * @param short_opt the corresponding short option (or '-' if none) + * @param additional_error possible further error specification + */ +static +int update_arg(void *field, char **orig_field, + unsigned int *field_given, unsigned int *prev_given, + char *value, const char *possible_values[], + const char *default_value, + cmdline_parser_arg_type arg_type, + int check_ambiguity, int override, + int no_free, int multiple_option, + const char *long_opt, char short_opt, + const char *additional_error) +{ + char *stop_char = 0; + const char *val = value; + int found; + char **string_field; + FIX_UNUSED (field); + + stop_char = 0; + found = 0; + + if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) + { + if (short_opt != '-') + fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", + package_name, long_opt, short_opt, + (additional_error ? additional_error : "")); + else + fprintf (stderr, "%s: `--%s' option given more than once%s\n", + package_name, long_opt, + (additional_error ? additional_error : "")); + return 1; /* failure */ + } + + if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0) + { + if (short_opt != '-') + fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n", + package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt, + (additional_error ? additional_error : "")); + else + fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n", + package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, + (additional_error ? additional_error : "")); + return 1; /* failure */ + } + + if (field_given && *field_given && ! override) + return 0; + if (prev_given) + (*prev_given)++; + if (field_given) + (*field_given)++; + if (possible_values) + val = possible_values[found]; + + switch(arg_type) { + case ARG_FLAG: + *((int *)field) = !*((int *)field); + break; + case ARG_STRING: + if (val) { + string_field = (char **)field; + if (!no_free && *string_field) + free (*string_field); /* free previous string */ + *string_field = gengetopt_strdup (val); + } + break; + default: + break; + }; + + + /* store the original value */ + switch(arg_type) { + case ARG_NO: + case ARG_FLAG: + break; + default: + if (value && orig_field) { + if (no_free) { + *orig_field = value; + } else { + if (*orig_field) + free (*orig_field); /* free previous string */ + *orig_field = gengetopt_strdup (value); + } + } + }; + + return 0; /* OK */ +} + + +int +cmdline_parser_internal ( + int argc, char **argv, struct gengetopt_args_info *args_info, + struct cmdline_parser_params *params, const char *additional_error) +{ + int c; /* Character of the parsed option. */ + + int error = 0; + struct gengetopt_args_info local_args_info; + + int override; + int initialize; + int check_required; + int check_ambiguity; + + package_name = argv[0]; + + override = params->override; + initialize = params->initialize; + check_required = params->check_required; + check_ambiguity = params->check_ambiguity; + + if (initialize) + cmdline_parser_init (args_info); + + cmdline_parser_init (&local_args_info); + + optarg = 0; + optind = 0; + opterr = params->print_errors; + optopt = '?'; + + while (1) + { + int option_index = 0; + + static struct option long_options[] = { + { "help", 0, NULL, 'h' }, + { "version", 0, NULL, 'V' }, + { "kernel", 1, NULL, 'i' }, + { "rootfs", 1, NULL, 'f' }, + { "output", 1, NULL, 'o' }, + { "cfe", 1, NULL, 0 }, + { "boardid", 1, NULL, 'b' }, + { "chipid", 1, NULL, 'c' }, + { "flash-start", 1, NULL, 's' }, + { "image-offset", 1, NULL, 'n' }, + { "tag-version", 1, NULL, 'v' }, + { "signature", 1, NULL, 'a' }, + { "signature2", 1, NULL, 'm' }, + { "block-size", 1, NULL, 'k' }, + { "load-addr", 1, NULL, 'l' }, + { "entry", 1, NULL, 'e' }, + { "layoutver", 1, NULL, 'y' }, + { "info1", 1, NULL, '1' }, + { "altinfo", 1, NULL, 0 }, + { "info2", 1, NULL, '2' }, + { "root-first", 0, NULL, 0 }, + { "rsa-signature", 1, NULL, 'r' }, + { "second-image-flag", 1, NULL, 0 }, + { "inactive", 1, NULL, 0 }, + { "reserved1", 1, NULL, 0 }, + { "reserved2", 1, NULL, 0 }, + { "kernel-file-has-header", 0, NULL, 0 }, + { 0, 0, 0, 0 } + }; + + c = getopt_long (argc, argv, "hVi:f:o:b:c:s:n:v:a:m:k:l:e:y:1:2:r:", long_options, &option_index); + + if (c == -1) break; /* Exit from `while (1)' loop. */ + + switch (c) + { + case 'h': /* Print help and exit. */ + cmdline_parser_print_help (); + cmdline_parser_free (&local_args_info); + exit (EXIT_SUCCESS); + + case 'V': /* Print version and exit. */ + cmdline_parser_print_version (); + cmdline_parser_free (&local_args_info); + exit (EXIT_SUCCESS); + + case 'i': /* File with LZMA compressed kernel to include in the image.. */ + + + if (update_arg( (void *)&(args_info->kernel_arg), + &(args_info->kernel_orig), &(args_info->kernel_given), + &(local_args_info.kernel_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "kernel", 'i', + additional_error)) + goto failure; + + break; + case 'f': /* File with RootFS to include in the image.. */ + + + if (update_arg( (void *)&(args_info->rootfs_arg), + &(args_info->rootfs_orig), &(args_info->rootfs_given), + &(local_args_info.rootfs_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "rootfs", 'f', + additional_error)) + goto failure; + + break; + case 'o': /* Name of output file.. */ + + + if (update_arg( (void *)&(args_info->output_arg), + &(args_info->output_orig), &(args_info->output_given), + &(local_args_info.output_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "output", 'o', + additional_error)) + goto failure; + + break; + case 'b': /* Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */ + + + if (update_arg( (void *)&(args_info->boardid_arg), + &(args_info->boardid_orig), &(args_info->boardid_given), + &(local_args_info.boardid_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "boardid", 'b', + additional_error)) + goto failure; + + break; + case 'c': /* Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */ + + + if (update_arg( (void *)&(args_info->chipid_arg), + &(args_info->chipid_orig), &(args_info->chipid_given), + &(local_args_info.chipid_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "chipid", 'c', + additional_error)) + goto failure; + + break; + case 's': /* Flash start address.. */ + + + if (update_arg( (void *)&(args_info->flash_start_arg), + &(args_info->flash_start_orig), &(args_info->flash_start_given), + &(local_args_info.flash_start_given), optarg, 0, "0xBFC00000", ARG_STRING, + check_ambiguity, override, 0, 0, + "flash-start", 's', + additional_error)) + goto failure; + + break; + case 'n': /* Offset from start address for the first byte after the CFE (in memory).. */ + + + if (update_arg( (void *)&(args_info->image_offset_arg), + &(args_info->image_offset_orig), &(args_info->image_offset_given), + &(local_args_info.image_offset_given), optarg, 0, "0x10000", ARG_STRING, + check_ambiguity, override, 0, 0, + "image-offset", 'n', + additional_error)) + goto failure; + + break; + case 'v': /* Version number for imagetag format.. */ + + + if (update_arg( (void *)&(args_info->tag_version_arg), + &(args_info->tag_version_orig), &(args_info->tag_version_given), + &(local_args_info.tag_version_given), optarg, 0, "6", ARG_STRING, + check_ambiguity, override, 0, 0, + "tag-version", 'v', + additional_error)) + goto failure; + + break; + case 'a': /* Magic string (signature), for boards that need it.. */ + + + if (update_arg( (void *)&(args_info->signature_arg), + &(args_info->signature_orig), &(args_info->signature_given), + &(local_args_info.signature_given), optarg, 0, "Broadcom Corporatio", ARG_STRING, + check_ambiguity, override, 0, 0, + "signature", 'a', + additional_error)) + goto failure; + + break; + case 'm': /* Second magic string (signature2).. */ + + + if (update_arg( (void *)&(args_info->signature2_arg), + &(args_info->signature2_orig), &(args_info->signature2_given), + &(local_args_info.signature2_given), optarg, 0, "ver. 2.0", ARG_STRING, + check_ambiguity, override, 0, 0, + "signature2", 'm', + additional_error)) + goto failure; + + break; + case 'k': /* Flash erase block size.. */ + + + if (update_arg( (void *)&(args_info->block_size_arg), + &(args_info->block_size_orig), &(args_info->block_size_given), + &(local_args_info.block_size_given), optarg, 0, "0x10000", ARG_STRING, + check_ambiguity, override, 0, 0, + "block-size", 'k', + additional_error)) + goto failure; + + break; + case 'l': /* Kernel load address.. */ + + + if (update_arg( (void *)&(args_info->load_addr_arg), + &(args_info->load_addr_orig), &(args_info->load_addr_given), + &(local_args_info.load_addr_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "load-addr", 'l', + additional_error)) + goto failure; + + break; + case 'e': /* Address where the kernel entry point will be for booting.. */ + + + if (update_arg( (void *)&(args_info->entry_arg), + &(args_info->entry_orig), &(args_info->entry_given), + &(local_args_info.entry_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "entry", 'e', + additional_error)) + goto failure; + + break; + case 'y': /* Flash layout version (version 2.2x of the Broadcom code requires this).. */ + + + if (update_arg( (void *)&(args_info->layoutver_arg), + &(args_info->layoutver_orig), &(args_info->layoutver_given), + &(local_args_info.layoutver_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "layoutver", 'y', + additional_error)) + goto failure; + + break; + case '1': /* String for first vendor information section.. */ + + + if (update_arg( (void *)&(args_info->info1_arg), + &(args_info->info1_orig), &(args_info->info1_given), + &(local_args_info.info1_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "info1", '1', + additional_error)) + goto failure; + + break; + case '2': /* String for second vendor information section.. */ + + + if (update_arg( (void *)&(args_info->info2_arg), + &(args_info->info2_orig), &(args_info->info2_given), + &(local_args_info.info2_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "info2", '2', + additional_error)) + goto failure; + + break; + case 'r': /* String for RSA Signature section.. */ + + + if (update_arg( (void *)&(args_info->rsa_signature_arg), + &(args_info->rsa_signature_orig), &(args_info->rsa_signature_given), + &(local_args_info.rsa_signature_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "rsa-signature", 'r', + additional_error)) + goto failure; + + break; + + case 0: /* Long option with no short option */ + /* File with CFE to include in the image.. */ + if (strcmp (long_options[option_index].name, "cfe") == 0) + { + + + if (update_arg( (void *)&(args_info->cfe_arg), + &(args_info->cfe_orig), &(args_info->cfe_given), + &(local_args_info.cfe_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "cfe", '-', + additional_error)) + goto failure; + + } + /* String for vendor information section (alternate/pirelli).. */ + else if (strcmp (long_options[option_index].name, "altinfo") == 0) + { + + + if (update_arg( (void *)&(args_info->altinfo_arg), + &(args_info->altinfo_orig), &(args_info->altinfo_given), + &(local_args_info.altinfo_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "altinfo", '-', + additional_error)) + goto failure; + + } + /* Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory).. */ + else if (strcmp (long_options[option_index].name, "root-first") == 0) + { + + + if (update_arg((void *)&(args_info->root_first_flag), 0, &(args_info->root_first_given), + &(local_args_info.root_first_given), optarg, 0, 0, ARG_FLAG, + check_ambiguity, override, 1, 0, "root-first", '-', + additional_error)) + goto failure; + + } + /* Dual Image Flag (2=not-specified).. */ + else if (strcmp (long_options[option_index].name, "second-image-flag") == 0) + { + + + if (update_arg( (void *)&(args_info->second_image_flag_arg), + &(args_info->second_image_flag_orig), &(args_info->second_image_flag_given), + &(local_args_info.second_image_flag_given), optarg, cmdline_parser_second_image_flag_values, "2", ARG_STRING, + check_ambiguity, override, 0, 0, + "second-image-flag", '-', + additional_error)) + goto failure; + + } + /* Inactive Flag (2=not-specified).. */ + else if (strcmp (long_options[option_index].name, "inactive") == 0) + { + + + if (update_arg( (void *)&(args_info->inactive_arg), + &(args_info->inactive_orig), &(args_info->inactive_given), + &(local_args_info.inactive_given), optarg, cmdline_parser_inactive_values, "2", ARG_STRING, + check_ambiguity, override, 0, 0, + "inactive", '-', + additional_error)) + goto failure; + + } + /* String for first reserved section.. */ + else if (strcmp (long_options[option_index].name, "reserved1") == 0) + { + + + if (update_arg( (void *)&(args_info->reserved1_arg), + &(args_info->reserved1_orig), &(args_info->reserved1_given), + &(local_args_info.reserved1_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "reserved1", '-', + additional_error)) + goto failure; + + } + /* String for second reserved section.. */ + else if (strcmp (long_options[option_index].name, "reserved2") == 0) + { + + + if (update_arg( (void *)&(args_info->reserved2_arg), + &(args_info->reserved2_orig), &(args_info->reserved2_given), + &(local_args_info.reserved2_given), optarg, 0, 0, ARG_STRING, + check_ambiguity, override, 0, 0, + "reserved2", '-', + additional_error)) + goto failure; + + } + /* Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed. */ + else if (strcmp (long_options[option_index].name, "kernel-file-has-header") == 0) + { + + + if (update_arg((void *)&(args_info->kernel_file_has_header_flag), 0, &(args_info->kernel_file_has_header_given), + &(local_args_info.kernel_file_has_header_given), optarg, 0, 0, ARG_FLAG, + check_ambiguity, override, 1, 0, "kernel-file-has-header", '-', + additional_error)) + goto failure; + + } + + break; + case '?': /* Invalid option. */ + /* `getopt_long' already printed an error message. */ + goto failure; + + default: /* bug: option not considered. */ + fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); + abort (); + } /* switch */ + } /* while */ + + + + if (check_required) + { + error += cmdline_parser_required2 (args_info, argv[0], additional_error); + } + + cmdline_parser_release (&local_args_info); + + if ( error ) + return (EXIT_FAILURE); + + return 0; + +failure: + + cmdline_parser_release (&local_args_info); + return (EXIT_FAILURE); +} diff --git a/tools/firmware-utils/src/imagetag_cmdline.h b/tools/firmware-utils/src/imagetag_cmdline.h new file mode 100644 index 000000000..a38914841 --- /dev/null +++ b/tools/firmware-utils/src/imagetag_cmdline.h @@ -0,0 +1,272 @@ +/** @file imagetag_cmdline.h + * @brief The header file for the command line option parser + * generated by GNU Gengetopt version 2.22.4 + * http://www.gnu.org/software/gengetopt. + * DO NOT modify this file, since it can be overwritten + * @author GNU Gengetopt by Lorenzo Bettini */ + +#ifndef IMAGETAG_CMDLINE_H +#define IMAGETAG_CMDLINE_H + +/* If we use autoconf. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> /* for FILE */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef CMDLINE_PARSER_PACKAGE +/** @brief the program name (used for printing errors) */ +#define CMDLINE_PARSER_PACKAGE "imagetag" +#endif + +#ifndef CMDLINE_PARSER_PACKAGE_NAME +/** @brief the complete program name (used for help and version) */ +#define CMDLINE_PARSER_PACKAGE_NAME "imagetag" +#endif + +#ifndef CMDLINE_PARSER_VERSION +/** @brief the program version */ +#define CMDLINE_PARSER_VERSION "2.0.0" +#endif + +/** @brief Where the command line options are stored */ +struct gengetopt_args_info +{ + const char *help_help; /**< @brief Print help and exit help description. */ + const char *version_help; /**< @brief Print version and exit help description. */ + char * kernel_arg; /**< @brief File with LZMA compressed kernel to include in the image.. */ + char * kernel_orig; /**< @brief File with LZMA compressed kernel to include in the image. original value given at command line. */ + const char *kernel_help; /**< @brief File with LZMA compressed kernel to include in the image. help description. */ + char * rootfs_arg; /**< @brief File with RootFS to include in the image.. */ + char * rootfs_orig; /**< @brief File with RootFS to include in the image. original value given at command line. */ + const char *rootfs_help; /**< @brief File with RootFS to include in the image. help description. */ + char * output_arg; /**< @brief Name of output file.. */ + char * output_orig; /**< @brief Name of output file. original value given at command line. */ + const char *output_help; /**< @brief Name of output file. help description. */ + char * cfe_arg; /**< @brief File with CFE to include in the image.. */ + char * cfe_orig; /**< @brief File with CFE to include in the image. original value given at command line. */ + const char *cfe_help; /**< @brief File with CFE to include in the image. help description. */ + char * boardid_arg; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */ + char * boardid_orig; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). original value given at command line. */ + const char *boardid_help; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). help description. */ + char * chipid_arg; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */ + char * chipid_orig; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). original value given at command line. */ + const char *chipid_help; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). help description. */ + char * flash_start_arg; /**< @brief Flash start address. (default='0xBFC00000'). */ + char * flash_start_orig; /**< @brief Flash start address. original value given at command line. */ + const char *flash_start_help; /**< @brief Flash start address. help description. */ + char * image_offset_arg; /**< @brief Offset from start address for the first byte after the CFE (in memory). (default='0x10000'). */ + char * image_offset_orig; /**< @brief Offset from start address for the first byte after the CFE (in memory). original value given at command line. */ + const char *image_offset_help; /**< @brief Offset from start address for the first byte after the CFE (in memory). help description. */ + char * tag_version_arg; /**< @brief Version number for imagetag format. (default='6'). */ + char * tag_version_orig; /**< @brief Version number for imagetag format. original value given at command line. */ + const char *tag_version_help; /**< @brief Version number for imagetag format. help description. */ + char * signature_arg; /**< @brief Magic string (signature), for boards that need it. (default='Broadcom Corporatio'). */ + char * signature_orig; /**< @brief Magic string (signature), for boards that need it. original value given at command line. */ + const char *signature_help; /**< @brief Magic string (signature), for boards that need it. help description. */ + char * signature2_arg; /**< @brief Second magic string (signature2). (default='ver. 2.0'). */ + char * signature2_orig; /**< @brief Second magic string (signature2). original value given at command line. */ + const char *signature2_help; /**< @brief Second magic string (signature2). help description. */ + char * block_size_arg; /**< @brief Flash erase block size. (default='0x10000'). */ + char * block_size_orig; /**< @brief Flash erase block size. original value given at command line. */ + const char *block_size_help; /**< @brief Flash erase block size. help description. */ + char * load_addr_arg; /**< @brief Kernel load address.. */ + char * load_addr_orig; /**< @brief Kernel load address. original value given at command line. */ + const char *load_addr_help; /**< @brief Kernel load address. help description. */ + char * entry_arg; /**< @brief Address where the kernel entry point will be for booting.. */ + char * entry_orig; /**< @brief Address where the kernel entry point will be for booting. original value given at command line. */ + const char *entry_help; /**< @brief Address where the kernel entry point will be for booting. help description. */ + char * layoutver_arg; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this).. */ + char * layoutver_orig; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). original value given at command line. */ + const char *layoutver_help; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). help description. */ + char * info1_arg; /**< @brief String for first vendor information section.. */ + char * info1_orig; /**< @brief String for first vendor information section. original value given at command line. */ + const char *info1_help; /**< @brief String for first vendor information section. help description. */ + char * altinfo_arg; /**< @brief String for vendor information section (alternate/pirelli).. */ + char * altinfo_orig; /**< @brief String for vendor information section (alternate/pirelli). original value given at command line. */ + const char *altinfo_help; /**< @brief String for vendor information section (alternate/pirelli). help description. */ + char * info2_arg; /**< @brief String for second vendor information section.. */ + char * info2_orig; /**< @brief String for second vendor information section. original value given at command line. */ + const char *info2_help; /**< @brief String for second vendor information section. help description. */ + int root_first_flag; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). (default=off). */ + const char *root_first_help; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). help description. */ + char * rsa_signature_arg; /**< @brief String for RSA Signature section.. */ + char * rsa_signature_orig; /**< @brief String for RSA Signature section. original value given at command line. */ + const char *rsa_signature_help; /**< @brief String for RSA Signature section. help description. */ + char * second_image_flag_arg; /**< @brief Dual Image Flag (2=not-specified). (default='2'). */ + char * second_image_flag_orig; /**< @brief Dual Image Flag (2=not-specified). original value given at command line. */ + const char *second_image_flag_help; /**< @brief Dual Image Flag (2=not-specified). help description. */ + char * inactive_arg; /**< @brief Inactive Flag (2=not-specified). (default='2'). */ + char * inactive_orig; /**< @brief Inactive Flag (2=not-specified). original value given at command line. */ + const char *inactive_help; /**< @brief Inactive Flag (2=not-specified). help description. */ + char * reserved1_arg; /**< @brief String for first reserved section.. */ + char * reserved1_orig; /**< @brief String for first reserved section. original value given at command line. */ + const char *reserved1_help; /**< @brief String for first reserved section. help description. */ + char * reserved2_arg; /**< @brief String for second reserved section.. */ + char * reserved2_orig; /**< @brief String for second reserved section. original value given at command line. */ + const char *reserved2_help; /**< @brief String for second reserved section. help description. */ + int kernel_file_has_header_flag; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed (default=off). */ + const char *kernel_file_has_header_help; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed help description. */ + + unsigned int help_given ; /**< @brief Whether help was given. */ + unsigned int version_given ; /**< @brief Whether version was given. */ + unsigned int kernel_given ; /**< @brief Whether kernel was given. */ + unsigned int rootfs_given ; /**< @brief Whether rootfs was given. */ + unsigned int output_given ; /**< @brief Whether output was given. */ + unsigned int cfe_given ; /**< @brief Whether cfe was given. */ + unsigned int boardid_given ; /**< @brief Whether boardid was given. */ + unsigned int chipid_given ; /**< @brief Whether chipid was given. */ + unsigned int flash_start_given ; /**< @brief Whether flash-start was given. */ + unsigned int image_offset_given ; /**< @brief Whether image-offset was given. */ + unsigned int tag_version_given ; /**< @brief Whether tag-version was given. */ + unsigned int signature_given ; /**< @brief Whether signature was given. */ + unsigned int signature2_given ; /**< @brief Whether signature2 was given. */ + unsigned int block_size_given ; /**< @brief Whether block-size was given. */ + unsigned int load_addr_given ; /**< @brief Whether load-addr was given. */ + unsigned int entry_given ; /**< @brief Whether entry was given. */ + unsigned int layoutver_given ; /**< @brief Whether layoutver was given. */ + unsigned int info1_given ; /**< @brief Whether info1 was given. */ + unsigned int altinfo_given ; /**< @brief Whether altinfo was given. */ + unsigned int info2_given ; /**< @brief Whether info2 was given. */ + unsigned int root_first_given ; /**< @brief Whether root-first was given. */ + unsigned int rsa_signature_given ; /**< @brief Whether rsa-signature was given. */ + unsigned int second_image_flag_given ; /**< @brief Whether second-image-flag was given. */ + unsigned int inactive_given ; /**< @brief Whether inactive was given. */ + unsigned int reserved1_given ; /**< @brief Whether reserved1 was given. */ + unsigned int reserved2_given ; /**< @brief Whether reserved2 was given. */ + unsigned int kernel_file_has_header_given ; /**< @brief Whether kernel-file-has-header was given. */ + +} ; + +/** @brief The additional parameters to pass to parser functions */ +struct cmdline_parser_params +{ + int override; /**< @brief whether to override possibly already present options (default 0) */ + int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ + int check_required; /**< @brief whether to check that all required options were provided (default 1) */ + int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ + int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ +} ; + +/** @brief the purpose string of the program */ +extern const char *gengetopt_args_info_purpose; +/** @brief the usage string of the program */ +extern const char *gengetopt_args_info_usage; +/** @brief all the lines making the help output */ +extern const char *gengetopt_args_info_help[]; + +/** + * The command line parser + * @param argc the number of command line options + * @param argv the command line options + * @param args_info the structure where option information will be stored + * @return 0 if everything went fine, NON 0 if an error took place + */ +int cmdline_parser (int argc, char **argv, + struct gengetopt_args_info *args_info); + +/** + * The command line parser (version with additional parameters - deprecated) + * @param argc the number of command line options + * @param argv the command line options + * @param args_info the structure where option information will be stored + * @param override whether to override possibly already present options + * @param initialize whether to initialize the option structure my_args_info + * @param check_required whether to check that all required options were provided + * @return 0 if everything went fine, NON 0 if an error took place + * @deprecated use cmdline_parser_ext() instead + */ +int cmdline_parser2 (int argc, char **argv, + struct gengetopt_args_info *args_info, + int override, int initialize, int check_required); + +/** + * The command line parser (version with additional parameters) + * @param argc the number of command line options + * @param argv the command line options + * @param args_info the structure where option information will be stored + * @param params additional parameters for the parser + * @return 0 if everything went fine, NON 0 if an error took place + */ +int cmdline_parser_ext (int argc, char **argv, + struct gengetopt_args_info *args_info, + struct cmdline_parser_params *params); + +/** + * Save the contents of the option struct into an already open FILE stream. + * @param outfile the stream where to dump options + * @param args_info the option struct to dump + * @return 0 if everything went fine, NON 0 if an error took place + */ +int cmdline_parser_dump(FILE *outfile, + struct gengetopt_args_info *args_info); + +/** + * Save the contents of the option struct into a (text) file. + * This file can be read by the config file parser (if generated by gengetopt) + * @param filename the file where to save + * @param args_info the option struct to save + * @return 0 if everything went fine, NON 0 if an error took place + */ +int cmdline_parser_file_save(const char *filename, + struct gengetopt_args_info *args_info); + +/** + * Print the help + */ +void cmdline_parser_print_help(void); +/** + * Print the version + */ +void cmdline_parser_print_version(void); + +/** + * Initializes all the fields a cmdline_parser_params structure + * to their default values + * @param params the structure to initialize + */ +void cmdline_parser_params_init(struct cmdline_parser_params *params); + +/** + * Allocates dynamically a cmdline_parser_params structure and initializes + * all its fields to their default values + * @return the created and initialized cmdline_parser_params structure + */ +struct cmdline_parser_params *cmdline_parser_params_create(void); + +/** + * Initializes the passed gengetopt_args_info structure's fields + * (also set default values for options that have a default) + * @param args_info the structure to initialize + */ +void cmdline_parser_init (struct gengetopt_args_info *args_info); +/** + * Deallocates the string fields of the gengetopt_args_info structure + * (but does not deallocate the structure itself) + * @param args_info the structure to deallocate + */ +void cmdline_parser_free (struct gengetopt_args_info *args_info); + +/** + * Checks that all the required options were specified + * @param args_info the structure to check + * @param prog_name the name of the program that will be used to print + * possible errors + * @return + */ +int cmdline_parser_required (struct gengetopt_args_info *args_info, + const char *prog_name); + +extern const char *cmdline_parser_second_image_flag_values[]; /**< @brief Possible values for second-image-flag. */ +extern const char *cmdline_parser_inactive_values[]; /**< @brief Possible values for inactive. */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* IMAGETAG_CMDLINE_H */ |