Example #1
0
/**
 * fit_image_get_os - get os id for a given component image node
 * @fit: pointer to the FIT format image header
 * @noffset: component image node offset
 * @os: pointer to the uint8_t, will hold os numeric id
 *
 * fit_image_get_os() finds os property in a given component image node.
 * If the property is found, its (string) value is translated to the numeric
 * id which is returned to the caller.
 *
 * returns:
 *     0, on success
 *     -1, on failure
 */
int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
{
	int len;
	const void *data;

	/* Get OS name from property data */
	data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
	if (data == NULL) {
		fit_get_debug(fit, noffset, FIT_OS_PROP, len);
		*os = -1;
		return -1;
	}

	/* Translate OS name to id */
	*os = genimg_get_os_id(data);
	return 0;
}
Example #2
0
static void process_args(int argc, char **argv)
{
	char *ptr;
	int type = IH_TYPE_INVALID;
	char *datafile = NULL;
	int opt;

	while ((opt = getopt(argc, argv,
			     "a:A:b:c:C:d:D:e:Ef:Fk:K:ln:p:O:rR:qsT:vVx")) != -1) {
		switch (opt) {
		case 'a':
			params.addr = strtoull(optarg, &ptr, 16);
			if (*ptr) {
				fprintf(stderr, "%s: invalid load address %s\n",
					params.cmdname, optarg);
				exit(EXIT_FAILURE);
			}
			break;
		case 'A':
			params.arch = genimg_get_arch_id(optarg);
			if (params.arch < 0) {
				show_valid_options(IH_ARCH);
				usage("Invalid architecture");
			}
			break;
		case 'b':
			if (add_content(IH_TYPE_FLATDT, optarg)) {
				fprintf(stderr,
					"%s: Out of memory adding content '%s'",
					params.cmdname, optarg);
				exit(EXIT_FAILURE);
			}
			break;
		case 'c':
			params.comment = optarg;
			break;
		case 'C':
			params.comp = genimg_get_comp_id(optarg);
			if (params.comp < 0) {
				show_valid_options(IH_COMP);
				usage("Invalid compression type");
			}
			break;
		case 'd':
			params.datafile = optarg;
			params.dflag = 1;
			break;
		case 'D':
			params.dtc = optarg;
			break;
		case 'e':
			params.ep = strtoull(optarg, &ptr, 16);
			if (*ptr) {
				fprintf(stderr, "%s: invalid entry point %s\n",
					params.cmdname, optarg);
				exit(EXIT_FAILURE);
			}
			params.eflag = 1;
			break;
		case 'E':
			params.external_data = true;
			break;
		case 'f':
			datafile = optarg;
			params.auto_its = !strcmp(datafile, "auto");
			/* no break */
		case 'F':
			/*
			 * The flattened image tree (FIT) format
			 * requires a flattened device tree image type
			 */
			params.type = IH_TYPE_FLATDT;
			params.fflag = 1;
			break;
		case 'k':
			params.keydir = optarg;
			break;
		case 'K':
			params.keydest = optarg;
			break;
		case 'l':
			params.lflag = 1;
			break;
		case 'n':
			params.imagename = optarg;
			break;
		case 'O':
			params.os = genimg_get_os_id(optarg);
			if (params.os < 0) {
				show_valid_options(IH_OS);
				usage("Invalid operating system");
			}
			break;
		case 'p':
			params.external_offset = strtoull(optarg, &ptr, 16);
			if (*ptr) {
				fprintf(stderr, "%s: invalid offset size %s\n",
					params.cmdname, optarg);
				exit(EXIT_FAILURE);
			}
			break;
		case 'q':
			params.quiet = 1;
			break;
		case 'r':
			params.require_keys = 1;
			break;
		case 'R':
			/*
			 * This entry is for the second configuration
			 * file, if only one is not enough.
			 */
			params.imagename2 = optarg;
			break;
		case 's':
			params.skipcpy = 1;
			break;
		case 'T':
			type = genimg_get_type_id(optarg);
			if (type < 0) {
				show_valid_options(IH_TYPE);
				usage("Invalid image type");
			}
			break;
		case 'v':
			params.vflag++;
			break;
		case 'V':
			printf("mkimage version %s\n", PLAIN_VERSION);
			exit(EXIT_SUCCESS);
		case 'x':
			params.xflag++;
			break;
		default:
			usage("Invalid option");
		}
	}

	/* The last parameter is expected to be the imagefile */
	if (optind < argc)
		params.imagefile = argv[optind];

	/*
	 * For auto-generated FIT images we need to know the image type to put
	 * in the FIT, which is separate from the file's image type (which
	 * will always be IH_TYPE_FLATDT in this case).
	 */
	if (params.type == IH_TYPE_FLATDT) {
		params.fit_image_type = type ? type : IH_TYPE_KERNEL;
		/* For auto_its, datafile is always 'auto' */
		if (!params.auto_its)
			params.datafile = datafile;
		else if (!params.datafile)
			usage("Missing data file for auto-FIT (use -d)");
	} else if (type != IH_TYPE_INVALID) {
		params.type = type;
	}

	if (!params.imagefile)
		usage("Missing output filename");
}
Example #3
0
int main(int argc, char **argv)
{
	int ifd = -1;
	struct stat sbuf;
	char *ptr;
	int retval = 0;
	struct image_type_params *tparams = NULL;
	int pad_len = 0;
	int dfd;

	params.cmdname = *argv;
	params.addr = params.ep = 0;

	while (--argc > 0 && **++argv == '-') {
		while (*++*argv) {
			switch (**argv) {
			case 'l':
				params.lflag = 1;
				break;
			case 'A':
				if ((--argc <= 0) ||
					(params.arch =
					genimg_get_arch_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'c':
				if (--argc <= 0)
					usage();
				params.comment = *++argv;
				goto NXTARG;
			case 'C':
				if ((--argc <= 0) ||
					(params.comp =
					genimg_get_comp_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'D':
				if (--argc <= 0)
					usage ();
				params.dtc = *++argv;
				goto NXTARG;

			case 'O':
				if ((--argc <= 0) ||
					(params.os =
					genimg_get_os_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'T':
				params.type = -1;
				if (--argc >= 0 && argv[1]) {
					params.type =
						genimg_get_type_id(*++argv);
				}
				if (params.type < 0) {
					show_image_types();
					usage();
				}
				goto NXTARG;
			case 'a':
				if (--argc <= 0)
					usage ();
				params.addr = strtoull(*++argv, &ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid load address %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				goto NXTARG;
			case 'd':
				if (--argc <= 0)
					usage ();
				params.datafile = *++argv;
				params.dflag = 1;
				goto NXTARG;
			case 'e':
				if (--argc <= 0)
					usage ();
				params.ep = strtoull(*++argv, &ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid entry point %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				params.eflag = 1;
				goto NXTARG;
			case 'f':
				if (--argc <= 0)
					usage ();
				params.datafile = *++argv;
				/* no break */
			case 'F':
				/*
				 * The flattened image tree (FIT) format
				 * requires a flattened device tree image type
				 */
				params.type = IH_TYPE_FLATDT;
				params.fflag = 1;
				goto NXTARG;
			case 'k':
				if (--argc <= 0)
					usage();
				params.keydir = *++argv;
				goto NXTARG;
			case 'K':
				if (--argc <= 0)
					usage();
				params.keydest = *++argv;
				goto NXTARG;
			case 'n':
				if (--argc <= 0)
					usage ();
				params.imagename = *++argv;
				goto NXTARG;
			case 'r':
				params.require_keys = 1;
				break;
			case 'R':
				if (--argc <= 0)
					usage();
				/*
				 * This entry is for the second configuration
				 * file, if only one is not enough.
				 */
				params.imagename2 = *++argv;
				goto NXTARG;
			case 's':
				params.skipcpy = 1;
				break;
			case 'v':
				params.vflag++;
				break;
			case 'V':
				printf("mkimage version %s\n", PLAIN_VERSION);
				exit(EXIT_SUCCESS);
			case 'x':
				params.xflag++;
				break;
			default:
				usage ();
			}
		}
NXTARG:		;
	}

	if (argc != 1)
		usage ();

	/* set tparams as per input type_id */
	tparams = imagetool_get_type(params.type);
	if (tparams == NULL) {
		fprintf (stderr, "%s: unsupported type %s\n",
			params.cmdname, genimg_get_type_name(params.type));
		exit (EXIT_FAILURE);
	}

	/*
	 * check the passed arguments parameters meets the requirements
	 * as per image type to be generated/listed
	 */
	if (tparams->check_params)
		if (tparams->check_params (&params))
			usage ();

	if (!params.eflag) {
		params.ep = params.addr;
		/* If XIP, entry point must be after the U-Boot header */
		if (params.xflag)
			params.ep += tparams->header_size;
	}

	params.imagefile = *argv;

	if (params.fflag){
		if (tparams->fflag_handle)
			/*
			 * in some cases, some additional processing needs
			 * to be done if fflag is defined
			 *
			 * For ex. fit_handle_file for Fit file support
			 */
			retval = tparams->fflag_handle(&params);

		if (retval != EXIT_SUCCESS)
			exit (retval);
	}

	if (params.lflag || params.fflag) {
		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
	} else {
		ifd = open (params.imagefile,
			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
	}

	if (ifd < 0) {
		fprintf (stderr, "%s: Can't open %s: %s\n",
			params.cmdname, params.imagefile,
			strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (params.lflag || params.fflag) {
		/*
		 * list header information of existing image
		 */
		if (fstat(ifd, &sbuf) < 0) {
			fprintf (stderr, "%s: Can't stat %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		if ((unsigned)sbuf.st_size < tparams->header_size) {
			fprintf (stderr,
				"%s: Bad size: \"%s\" is not valid image\n",
				params.cmdname, params.imagefile);
			exit (EXIT_FAILURE);
		}

		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
		if (ptr == MAP_FAILED) {
			fprintf (stderr, "%s: Can't read %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		/*
		 * scan through mkimage registry for all supported image types
		 * and verify the input image file header for match
		 * Print the image information for matched image type
		 * Returns the error code if not matched
		 */
		retval = imagetool_verify_print_header(ptr, &sbuf,
				tparams, &params);

		(void) munmap((void *)ptr, sbuf.st_size);
		(void) close (ifd);

		exit (retval);
	}

	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) {
		dfd = open(params.datafile, O_RDONLY | O_BINARY);
		if (dfd < 0) {
			fprintf(stderr, "%s: Can't open %s: %s\n",
				params.cmdname, params.datafile,
				strerror(errno));
			exit(EXIT_FAILURE);
		}

		if (fstat(dfd, &sbuf) < 0) {
			fprintf(stderr, "%s: Can't stat %s: %s\n",
				params.cmdname, params.datafile,
				strerror(errno));
			exit(EXIT_FAILURE);
		}

		params.file_size = sbuf.st_size + tparams->header_size;
		close(dfd);
	}

	/*
	 * In case there an header with a variable
	 * length will be added, the corresponding
	 * function is called. This is responsible to
	 * allocate memory for the header itself.
	 */
	if (tparams->vrec_header)
		pad_len = tparams->vrec_header(&params, tparams);
	else
		memset(tparams->hdr, 0, tparams->header_size);

	if (write(ifd, tparams->hdr, tparams->header_size)
					!= tparams->header_size) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (!params.skipcpy) {
		if (params.type == IH_TYPE_MULTI ||
		    params.type == IH_TYPE_SCRIPT) {
			char *file = params.datafile;
			uint32_t size;

			for (;;) {
				char *sep = NULL;

				if (file) {
					if ((sep = strchr(file, ':')) != NULL) {
						*sep = '\0';
					}

					if (stat (file, &sbuf) < 0) {
						fprintf (stderr, "%s: Can't stat %s: %s\n",
							 params.cmdname, file, strerror(errno));
						exit (EXIT_FAILURE);
					}
					size = cpu_to_uimage (sbuf.st_size);
				} else {
					size = 0;
				}

				if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
					fprintf (stderr, "%s: Write error on %s: %s\n",
						 params.cmdname, params.imagefile,
						 strerror(errno));
					exit (EXIT_FAILURE);
				}

				if (!file) {
					break;
				}

				if (sep) {
					*sep = ':';
					file = sep + 1;
				} else {
					file = NULL;
				}
			}

			file = params.datafile;

			for (;;) {
				char *sep = strchr(file, ':');
				if (sep) {
					*sep = '\0';
					copy_file (ifd, file, 1);
					*sep++ = ':';
					file = sep;
				} else {
					copy_file (ifd, file, 0);
					break;
				}
			}
		} else if (params.type == IH_TYPE_PBLIMAGE) {
			/* PBL has special Image format, implements its' own */
			pbl_load_uboot(ifd, &params);
		} else {
			copy_file(ifd, params.datafile, pad_len);
		}
	}

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__OpenBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (fstat(ifd, &sbuf) < 0) {
		fprintf (stderr, "%s: Can't stat %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}
	params.file_size = sbuf.st_size;

	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
	if (ptr == MAP_FAILED) {
		fprintf (stderr, "%s: Can't map %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Setup the image header as per input image type*/
	if (tparams->set_header)
		tparams->set_header (ptr, &sbuf, ifd, &params);
	else {
		fprintf (stderr, "%s: Can't set header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Print the image information by processing image header */
	if (tparams->print_header)
		tparams->print_header (ptr);
	else {
		fprintf (stderr, "%s: Can't print header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	(void) munmap((void *)ptr, sbuf.st_size);

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__OpenBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (close(ifd)) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}
Example #4
0
int
main (int argc, char **argv)
{
	int ifd = -1;
	uint32_t checksum;
	uint32_t addr;
	uint32_t ep;
	struct stat sbuf;
	unsigned char *ptr;
	char *name = "";

	cmdname = *argv;

	addr = ep = 0;

	while (--argc > 0 && **++argv == '-') {
		while (*++*argv) {
			switch (**argv) {
			case 'l':
				lflag = 1;
				break;
			case 'A':
				if ((--argc <= 0) ||
				    (opt_arch = genimg_get_arch_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'C':
				if ((--argc <= 0) ||
				    (opt_comp = genimg_get_comp_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'D':
				if (--argc <= 0)
					usage ();
				opt_dtc = *++argv;
				goto NXTARG;

			case 'O':
				if ((--argc <= 0) ||
				    (opt_os = genimg_get_os_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'T':
				if ((--argc <= 0) ||
				    (opt_type = genimg_get_type_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'a':
				if (--argc <= 0)
					usage ();
				addr = strtoul (*++argv, (char **)&ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid load address %s\n",
						cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				goto NXTARG;
			case 'd':
				if (--argc <= 0)
					usage ();
				datafile = *++argv;
				dflag = 1;
				goto NXTARG;
			case 'e':
				if (--argc <= 0)
					usage ();
				ep = strtoul (*++argv, (char **)&ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid entry point %s\n",
						cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				eflag = 1;
				goto NXTARG;
			case 'f':
				if (--argc <= 0)
					usage ();
				datafile = *++argv;
				fflag = 1;
				goto NXTARG;
			case 'n':
				if (--argc <= 0)
					usage ();
				name = *++argv;
				goto NXTARG;
			case 'v':
				vflag++;
				break;
			case 'x':
				xflag++;
				break;
			default:
				usage ();
			}
		}
NXTARG:		;
	}

	if ((argc != 1) ||
		(dflag && (fflag || lflag)) ||
		(fflag && (dflag || lflag)) ||
		(lflag && (dflag || fflag)))
		usage();

	if (!eflag) {
		ep = addr;
		/* If XIP, entry point must be after the U-Boot header */
		if (xflag)
			ep += image_get_header_size ();
	}

	/*
	 * If XIP, ensure the entry point is equal to the load address plus
	 * the size of the U-Boot header.
	 */
	if (xflag) {
		if (ep != addr + image_get_header_size ()) {
			fprintf (stderr,
				"%s: For XIP, the entry point must be the load addr + %lu\n",
				cmdname,
				(unsigned long)image_get_header_size ());
			exit (EXIT_FAILURE);
		}
	}

	imagefile = *argv;

	if (!fflag){
		if (lflag) {
			ifd = open (imagefile, O_RDONLY|O_BINARY);
		} else {
			ifd = open (imagefile,
				O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
		}

		if (ifd < 0) {
			fprintf (stderr, "%s: Can't open %s: %s\n",
				cmdname, imagefile, strerror(errno));
			exit (EXIT_FAILURE);
		}
	}

	if (lflag) {
		/*
		 * list header information of existing image
		 */
		if (fstat(ifd, &sbuf) < 0) {
			fprintf (stderr, "%s: Can't stat %s: %s\n",
				cmdname, imagefile, strerror(errno));
			exit (EXIT_FAILURE);
		}

		if ((unsigned)sbuf.st_size < image_get_header_size ()) {
			fprintf (stderr,
				"%s: Bad size: \"%s\" is no valid image\n",
				cmdname, imagefile);
			exit (EXIT_FAILURE);
		}

		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
		if (ptr == MAP_FAILED) {
			fprintf (stderr, "%s: Can't read %s: %s\n",
				cmdname, imagefile, strerror(errno));
			exit (EXIT_FAILURE);
		}

		if (fdt_check_header (ptr)) {
			/* old-style image */
			image_verify_header ((char *)ptr, sbuf.st_size);
			image_print_contents ((image_header_t *)ptr);
		} else {
			/* FIT image */
			fit_print_contents (ptr);
		}

		(void) munmap((void *)ptr, sbuf.st_size);
		(void) close (ifd);

		exit (EXIT_SUCCESS);
	} else if (fflag) {
		/* Flattened Image Tree (FIT) format  handling */
		debug ("FIT format handling\n");
		fit_handle_file ();
		exit (EXIT_SUCCESS);
	}

	/*
	 * Must be -w then:
	 *
	 * write dummy header, to be fixed later
	 */
	memset (hdr, 0, image_get_header_size ());

	if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			cmdname, imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) {
		char *file = datafile;
		uint32_t size;

		for (;;) {
			char *sep = NULL;

			if (file) {
				if ((sep = strchr(file, ':')) != NULL) {
					*sep = '\0';
				}

				if (stat (file, &sbuf) < 0) {
					fprintf (stderr, "%s: Can't stat %s: %s\n",
						cmdname, file, strerror(errno));
					exit (EXIT_FAILURE);
				}
				size = cpu_to_uimage (sbuf.st_size);
			} else {
				size = 0;
			}

			if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
				fprintf (stderr, "%s: Write error on %s: %s\n",
					cmdname, imagefile, strerror(errno));
				exit (EXIT_FAILURE);
			}

			if (!file) {
				break;
			}

			if (sep) {
				*sep = ':';
				file = sep + 1;
			} else {
				file = NULL;
			}
		}

		file = datafile;

		for (;;) {
			char *sep = strchr(file, ':');
			if (sep) {
				*sep = '\0';
				copy_file (ifd, file, 1);
				*sep++ = ':';
				file = sep;
			} else {
				copy_file (ifd, file, 0);
				break;
			}
		}
	} else {
		copy_file (ifd, datafile, 0);
	}

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (fstat(ifd, &sbuf) < 0) {
		fprintf (stderr, "%s: Can't stat %s: %s\n",
			cmdname, imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
	if (ptr == MAP_FAILED) {
		fprintf (stderr, "%s: Can't map %s: %s\n",
			cmdname, imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	hdr = (image_header_t *)ptr;

	checksum = crc32 (0,
			  (const char *)(ptr + image_get_header_size ()),
			  sbuf.st_size - image_get_header_size ()
			 );

	/* Build new header */
	image_set_magic (hdr, IH_MAGIC);
	image_set_time (hdr, sbuf.st_mtime);
	image_set_size (hdr, sbuf.st_size - image_get_header_size ());
	image_set_load (hdr, addr);
	image_set_ep (hdr, ep);
	image_set_dcrc (hdr, checksum);
	image_set_os (hdr, opt_os);
	image_set_arch (hdr, opt_arch);
	image_set_type (hdr, opt_type);
	image_set_comp (hdr, opt_comp);

	image_set_name (hdr, name);

	checksum = crc32 (0, (const char *)hdr, image_get_header_size ());

	image_set_hcrc (hdr, checksum);

	image_print_contents (hdr);

	(void) munmap((void *)ptr, sbuf.st_size);

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (close(ifd)) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			cmdname, imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}
int
main (int argc, char **argv)
{
	int ifd = -1;
	struct stat sbuf;
	unsigned char *ptr;
	int retval = 0;
	struct image_type_params *tparams = NULL;

	/* Init Kirkwood Boot image generation/list support */
	init_kwb_image_type ();
	/* Init Freescale imx Boot image generation/list support */
	init_imx_image_type ();
	/* Init FIT image generation/list support */
	init_fit_image_type ();
	/* Init Default image generation/list support */
	init_default_image_type ();

	params.cmdname = *argv;
	params.addr = params.ep = 0;

	while (--argc > 0 && **++argv == '-') {
		while (*++*argv) {
			switch (**argv) {
			case 'l':
				params.lflag = 1;
				break;
			case 'A':
				if ((--argc <= 0) ||
					(params.arch =
					genimg_get_arch_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'C':
				if ((--argc <= 0) ||
					(params.comp =
					genimg_get_comp_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'D':
				if (--argc <= 0)
					usage ();
				params.dtc = *++argv;
				goto NXTARG;

			case 'O':
				if ((--argc <= 0) ||
					(params.os =
					genimg_get_os_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'T':
				if ((--argc <= 0) ||
					(params.type =
					genimg_get_type_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'a':
				if (--argc <= 0)
					usage ();
				params.addr = strtoul (*++argv,
					(char **)&ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid load address %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				goto NXTARG;
			case 'd':
				if (--argc <= 0)
					usage ();
				params.datafile = *++argv;
				params.dflag = 1;
				goto NXTARG;
			case 'e':
				if (--argc <= 0)
					usage ();
				params.ep = strtoul (*++argv,
						(char **)&ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid entry point %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				params.eflag = 1;
				goto NXTARG;
			case 'f':
				if (--argc <= 0)
					usage ();
				/*
				 * The flattened image tree (FIT) format
				 * requires a flattened device tree image type
				 */
				params.type = IH_TYPE_FLATDT;
				params.datafile = *++argv;
				params.fflag = 1;
				goto NXTARG;
			case 'n':
				if (--argc <= 0)
					usage ();
				params.imagename = *++argv;
				goto NXTARG;
			case 'v':
				params.vflag++;
				break;
			case 'x':
				params.xflag++;
				break;
			default:
				usage ();
			}
		}
NXTARG:		;
	}

	if (argc != 1)
		usage ();

	/* set tparams as per input type_id */
	tparams = mkimage_get_type(params.type);
	if (tparams == NULL) {
		fprintf (stderr, "%s: unsupported type %s\n",
			params.cmdname, genimg_get_type_name(params.type));
		exit (EXIT_FAILURE);
	}

	/*
	 * check the passed arguments parameters meets the requirements
	 * as per image type to be generated/listed
	 */
	if (tparams->check_params)
		if (tparams->check_params (&params))
			usage ();

	if (!params.eflag) {
		params.ep = params.addr;
		/* If XIP, entry point must be after the U-Boot header */
		if (params.xflag)
			params.ep += tparams->header_size;
	}

	params.imagefile = *argv;

	if (params.fflag){
		if (tparams->fflag_handle)
			/*
			 * in some cases, some additional processing needs
			 * to be done if fflag is defined
			 *
			 * For ex. fit_handle_file for Fit file support
			 */
			retval = tparams->fflag_handle(&params);

		if (retval != EXIT_SUCCESS)
			exit (retval);
	}

	if (params.lflag || params.fflag) {
		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
	} else {
		ifd = open (params.imagefile,
			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
	}

	if (ifd < 0) {
		fprintf (stderr, "%s: Can't open %s: %s\n",
			params.cmdname, params.imagefile,
			strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (params.lflag || params.fflag) {
		/*
		 * list header information of existing image
		 */
		if (fstat(ifd, &sbuf) < 0) {
			fprintf (stderr, "%s: Can't stat %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		if ((unsigned)sbuf.st_size < tparams->header_size) {
			fprintf (stderr,
				"%s: Bad size: \"%s\" is not valid image\n",
				params.cmdname, params.imagefile);
			exit (EXIT_FAILURE);
		}

		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
		if (ptr == MAP_FAILED) {
			fprintf (stderr, "%s: Can't read %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		/*
		 * scan through mkimage registry for all supported image types
		 * and verify the input image file header for match
		 * Print the image information for matched image type
		 * Returns the error code if not matched
		 */
		retval = mkimage_verify_print_header (ptr, &sbuf);

		(void) munmap((void *)ptr, sbuf.st_size);
		(void) close (ifd);

		exit (retval);
	}

	/*
	 * Must be -w then:
	 *
	 * write dummy header, to be fixed later
	 */
	memset (tparams->hdr, 0, tparams->header_size);

	if (write(ifd, tparams->hdr, tparams->header_size)
					!= tparams->header_size) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (params.type == IH_TYPE_MULTI || params.type == IH_TYPE_SCRIPT) {
		char *file = params.datafile;
		uint32_t size;

		for (;;) {
			char *sep = NULL;

			if (file) {
				if ((sep = strchr(file, ':')) != NULL) {
					*sep = '\0';
				}

				if (stat (file, &sbuf) < 0) {
					fprintf (stderr, "%s: Can't stat %s: %s\n",
						params.cmdname, file, strerror(errno));
					exit (EXIT_FAILURE);
				}
				size = cpu_to_uimage (sbuf.st_size);
			} else {
				size = 0;
			}

			if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
				fprintf (stderr, "%s: Write error on %s: %s\n",
					params.cmdname, params.imagefile,
					strerror(errno));
				exit (EXIT_FAILURE);
			}

			if (!file) {
				break;
			}

			if (sep) {
				*sep = ':';
				file = sep + 1;
			} else {
				file = NULL;
			}
		}

		file = params.datafile;

		for (;;) {
			char *sep = strchr(file, ':');
			if (sep) {
				*sep = '\0';
				copy_file (ifd, file, 1);
				*sep++ = ':';
				file = sep;
			} else {
				copy_file (ifd, file, 0);
				break;
			}
		}
	} else {
		copy_file (ifd, params.datafile, 0);
	}

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (fstat(ifd, &sbuf) < 0) {
		fprintf (stderr, "%s: Can't stat %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
	if (ptr == MAP_FAILED) {
		fprintf (stderr, "%s: Can't map %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Setup the image header as per input image type*/
	if (tparams->set_header)
		tparams->set_header (ptr, &sbuf, ifd, &params);
	else {
		fprintf (stderr, "%s: Can't set header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Print the image information by processing image header */
	if (tparams->print_header)
		tparams->print_header (ptr);
	else {
		fprintf (stderr, "%s: Can't print header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	(void) munmap((void *)ptr, sbuf.st_size);

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (close(ifd)) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}
Example #6
0
int
main (int argc, char **argv)
{
	long imagelen; /* CWWeng 2014/4/30 */
	int aes_blockno; /* CWWeng 2014/4/30 */
	aes_context ctx; /* CWWeng 2014/5/12 add */
	int ifd = -1;
	struct stat sbuf;
	char *ptr;
	int retval = 0;
	struct image_type_params *tparams = NULL;

	/* Init Freescale PBL Boot image generation/list support */
	init_pbl_image_type();
	/* Init Kirkwood Boot image generation/list support */
	init_kwb_image_type ();
	/* Init Freescale imx Boot image generation/list support */
	init_imx_image_type ();
	/* Init FIT image generation/list support */
	init_fit_image_type ();
	/* Init TI OMAP Boot image generation/list support */
	init_omap_image_type();
	/* Init Default image generation/list support */
	init_default_image_type ();
	/* Init Davinci UBL support */
	init_ubl_image_type();
	/* Init Davinci AIS support */
	init_ais_image_type();

	params.cmdname = *argv;
	params.addr = params.ep = 0;

	while (--argc > 0 && **++argv == '-') {
		while (*++*argv) {
			switch (**argv) {
			case 'l':
				params.lflag = 1;
				break;
			case 'A':
				if ((--argc <= 0) ||
					(params.arch =
					genimg_get_arch_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'C':
				if ((--argc <= 0) ||
					(params.comp =
					genimg_get_comp_id (*++argv)) < 0)
					usage ();
				goto NXTARG;
			case 'D':
				if (--argc <= 0)
					usage ();
				params.dtc = *++argv;
				goto NXTARG;

			case 'E': /* CWWeng 2014/4/29 add */
				if ((--argc <= 0) ||  
					(params.encrypt = 
					genimg_get_encrypt_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'K': /* CWWeng 2015/2/6 add */
				if (--argc <= 0)
					usage ();
				params.keyfile = *++argv;
				params.kflag = 1;
				goto NXTARG;

			case 'O':
				if ((--argc <= 0) ||
					(params.os =
					genimg_get_os_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'S': /* CWWeng 2015/3/5 add */
				if ((--argc <= 0) ||
					(params.checksum =
					genimg_get_checksum_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'T':
				if ((--argc <= 0) ||
					(params.type =
					genimg_get_type_id (*++argv)) < 0)
					usage ();
				goto NXTARG;

			case 'a':
				if (--argc <= 0)
					usage ();
				params.addr = strtoul (*++argv, &ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid load address %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				goto NXTARG;
			case 'd':
				if (--argc <= 0)
					usage ();
				params.datafile = *++argv;
				params.dflag = 1;
				goto NXTARG;
			case 'e':
				if (--argc <= 0)
					usage ();
				params.ep = strtoul (*++argv, &ptr, 16);
				if (*ptr) {
					fprintf (stderr,
						"%s: invalid entry point %s\n",
						params.cmdname, *argv);
					exit (EXIT_FAILURE);
				}
				params.eflag = 1;
				goto NXTARG;
			case 'f':
				if (--argc <= 0)
					usage ();
				/*
				 * The flattened image tree (FIT) format
				 * requires a flattened device tree image type
				 */
				params.type = IH_TYPE_FLATDT;
				params.datafile = *++argv;
				params.fflag = 1;
				goto NXTARG;
			case 'n':
				if (--argc <= 0)
					usage ();
				params.imagename = *++argv;
				goto NXTARG;
			case 'R':
				if (--argc <= 0)
					usage();
				/*
				 * This entry is for the second configuration
				 * file, if only one is not enough.
				 */
				params.imagename2 = *++argv;
				goto NXTARG;
			case 's':
				params.skipcpy = 1;
				break;
			case 'v':
				params.vflag++;
				break;
			case 'V':
				printf("mkimage version %s\n", PLAIN_VERSION);
				exit(EXIT_SUCCESS);
			case 'x':
				params.xflag++;
				break;
			default:
				usage ();
			}
		}
NXTARG:		;
	}

	if (argc != 1)
		usage ();

	/* set tparams as per input type_id */
	tparams = mkimage_get_type(params.type);
	if (tparams == NULL) {
		fprintf (stderr, "%s: unsupported type %s\n",
			params.cmdname, genimg_get_type_name(params.type));
		exit (EXIT_FAILURE);
	}

	/*
	 * check the passed arguments parameters meets the requirements
	 * as per image type to be generated/listed
	 */
	if (tparams->check_params)
		if (tparams->check_params (&params))
			usage ();

	if (!params.eflag) {
		params.ep = params.addr;
		/* If XIP, entry point must be after the U-Boot header */
		if (params.xflag)
			params.ep += tparams->header_size;
	}

	params.imagefile = *argv;

	if (params.fflag){
		if (tparams->fflag_handle)
			/*
			 * in some cases, some additional processing needs
			 * to be done if fflag is defined
			 *
			 * For ex. fit_handle_file for Fit file support
			 */
			retval = tparams->fflag_handle(&params);

		if (retval != EXIT_SUCCESS)
			exit (retval);
	}

	/* CWWeng 2015/2/6 add to read key file */
	if (params.kflag) 
		_read_key(params.cmdname, params.keyfile);
	

	if (params.lflag || params.fflag) {
		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
	} else {
		ifd = open (params.imagefile,
			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
	}

	if (ifd < 0) {
		fprintf (stderr, "%s: Can't open %s: %s\n",
			params.cmdname, params.imagefile,
			strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (params.lflag || params.fflag) {
		/*
		 * list header information of existing image
		 */
		if (fstat(ifd, &sbuf) < 0) {
			fprintf (stderr, "%s: Can't stat %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		if ((unsigned)sbuf.st_size < tparams->header_size) {
			fprintf (stderr,
				"%s: Bad size: \"%s\" is not valid image\n",
				params.cmdname, params.imagefile);
			exit (EXIT_FAILURE);
		}

		/* CWWeng 2014/5/28 : append 0 to the end of image 
		 * aes_encrypt() encrypt one 128 bit block
		 * if the image is not multiple of 16 byte (128 bit),
		 * patch 0 to the end of the image
		 */
		if (params.encrypt == IH_ENCRPT_AES) {
			char ch[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
			lseek(ifd,0,SEEK_END);
			if (sbuf.st_size % 16)
				write(ifd,ch, 16 - (sbuf.st_size % 16));
		}

		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
		if (ptr == MAP_FAILED) {
			fprintf (stderr, "%s: Can't read %s: %s\n",
				params.cmdname, params.imagefile,
				strerror(errno));
			exit (EXIT_FAILURE);
		}

		/*
		 * scan through mkimage registry for all supported image types
		 * and verify the input image file header for match
		 * Print the image information for matched image type
		 * Returns the error code if not matched
		 */
		retval = mkimage_verify_print_header (ptr, &sbuf);

		/*
		 * CWWeng 2014/4/30 : encrypt the image
		 * aes_encrypt() encrypt one 128 bit block
		 * if the image is not multiple of 16 byte (128 bit),
		 * patch 0 to the end of the image
		 */
		if (params.encrypt == IH_ENCRPT_AES) {
			int i;
			u8 temp_key;
			for (i=0; i<32; i+=4)
			{
				temp_key = otp_key[i];
				otp_key[i] = otp_key[i+3];
				otp_key[i+3] = temp_key;
				
				temp_key = otp_key[i+1];
				otp_key[i+1] = otp_key[i+2];
				otp_key[i+2] = temp_key;
			}

			for (i=0; i<32; i+=4)
				printf("Key%d = 0x%02x%02x%02x%02x\n",i/4,otp_key[i],otp_key[i+1],otp_key[i+2],otp_key[i+3]);

			aes_set_key(&ctx, (u8 *)otp_key, 256);
			imagelen = sbuf.st_size + 64;
			aes_blockno = 0;
			do
			{
				aes_encrypt(&ctx, (u8 *)(ptr+(16*aes_blockno)), (u8 *)(ptr+(16*aes_blockno)));
				imagelen -= 16;
				aes_blockno++;
			} while (imagelen > 0);
		}

		(void) munmap((void *)ptr, sbuf.st_size);
		(void) close (ifd);

		exit (retval);
	}

	/*
	 * In case there an header with a variable
	 * length will be added, the corresponding
	 * function is called. This is responsible to
	 * allocate memory for the header itself.
	 */
	if (tparams->vrec_header)
		tparams->vrec_header(&params, tparams);
	else
		memset(tparams->hdr, 0, tparams->header_size);

	if (write(ifd, tparams->hdr, tparams->header_size)
					!= tparams->header_size) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	if (!params.skipcpy) {
		if (params.type == IH_TYPE_MULTI ||
		    params.type == IH_TYPE_SCRIPT) {
			char *file = params.datafile;
			uint32_t size;

			for (;;) {
				char *sep = NULL;

				if (file) {
					if ((sep = strchr(file, ':')) != NULL) {
						*sep = '\0';
					}

					if (stat (file, &sbuf) < 0) {
						fprintf (stderr, "%s: Can't stat %s: %s\n",
							 params.cmdname, file, strerror(errno));
						exit (EXIT_FAILURE);
					}
					size = cpu_to_uimage (sbuf.st_size);
				} else {
					size = 0;
				}

				if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
					fprintf (stderr, "%s: Write error on %s: %s\n",
						 params.cmdname, params.imagefile,
						 strerror(errno));
					exit (EXIT_FAILURE);
				}

				if (!file) {
					break;
				}

				if (sep) {
					*sep = ':';
					file = sep + 1;
				} else {
					file = NULL;
				}
			}

			file = params.datafile;

			for (;;) {
				char *sep = strchr(file, ':');
				if (sep) {
					*sep = '\0';
					copy_file (ifd, file, 1);
					*sep++ = ':';
					file = sep;
				} else {
					copy_file (ifd, file, 0);
					break;
				}
			}
		} else if (params.type == IH_TYPE_PBLIMAGE) {
			/* PBL has special Image format, implements its' own */
			pbl_load_uboot(ifd, &params);
		} else {
			copy_file (ifd, params.datafile, 0);
		}
	}

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (fstat(ifd, &sbuf) < 0) {
		fprintf (stderr, "%s: Can't stat %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* CWWeng 2014/5/28 : append 0 to the end of image
	 * aes_encrypt() encrypt one 128 bit block
	 * if the image is not multiple of 16 byte (128 bit),
	 * patch 0 to the end of the image
	 */
	if (params.encrypt == IH_ENCRPT_AES) {
		char ch[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
		lseek(ifd,0,SEEK_END);
		if (sbuf.st_size % 16)
			write(ifd,ch, 16 - (sbuf.st_size % 16));
	}

	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
	if (ptr == MAP_FAILED) {
		fprintf (stderr, "%s: Can't map %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Setup the image header as per input image type*/
	if (tparams->set_header)
		tparams->set_header (ptr, &sbuf, ifd, &params);
	else {
		fprintf (stderr, "%s: Can't set header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/* Print the image information by processing image header */
	if (tparams->print_header)
		tparams->print_header (ptr);
	else {
		fprintf (stderr, "%s: Can't print header for %s: %s\n",
			params.cmdname, tparams->name, strerror(errno));
		exit (EXIT_FAILURE);
	}

	/*
	 * CWWeng 2014/4/30 : encrypt the image
	 * aes_encrypt() encrypt one 128 bit block
	 * if the image is not multiple of 16 byte (128 bit),
	 * patch 0 to the end of the image
	 */
	if (params.encrypt == IH_ENCRPT_AES) {
		int i;
		u8 temp_key;
		for (i=0; i<32; i+=4)
		{
			temp_key = otp_key[i];
			otp_key[i] = otp_key[i+3];
			otp_key[i+3] = temp_key;
				
			temp_key = otp_key[i+1];
			otp_key[i+1] = otp_key[i+2];
			otp_key[i+2] = temp_key;
		}

		for (i=0; i<32; i+=4)
			printf("Key%d = 0x%02x%02x%02x%02x\n",i/4,otp_key[i],otp_key[i+1],otp_key[i+2],otp_key[i+3]);

		aes_set_key(&ctx, (u8 *)otp_key, 256);
		imagelen = sbuf.st_size + 64;
		aes_blockno = 0;
		do
		{
			aes_encrypt(&ctx, (u8 *)(ptr+(16*aes_blockno)), (u8 *)(ptr+(16*aes_blockno)));
			imagelen -= 16;
			aes_blockno++;
		} while (imagelen > 0);
	}

	(void) munmap((void *)ptr, sbuf.st_size);

	/* We're a bit of paranoid */
#if defined(_POSIX_SYNCHRONIZED_IO) && \
   !defined(__sun__) && \
   !defined(__FreeBSD__) && \
   !defined(__APPLE__)
	(void) fdatasync (ifd);
#else
	(void) fsync (ifd);
#endif

	if (close(ifd)) {
		fprintf (stderr, "%s: Write error on %s: %s\n",
			params.cmdname, params.imagefile, strerror(errno));
		exit (EXIT_FAILURE);
	}

	exit (EXIT_SUCCESS);
}