int main()

in tools/ifdtool.c [811:1109]


int main(int argc, char *argv[])
{
	int opt, option_index = 0;
	int mode_dump = 0, mode_extract = 0, mode_inject = 0;
	int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
	int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
	int create = 0;
	char *region_type_string = NULL, *inject_fname = NULL;
	char *desc_fname = NULL, *addr_str = NULL;
	int region_type = -1, inputfreq = 0;
	enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
	struct input_file input_file[WRITE_MAX], *ifile, *fdt = NULL;
	unsigned char wr_idx, wr_num = 0;
	int rom_size = -1;
	bool write_it;
	char *filename;
	char *outfile = NULL;
	struct stat buf;
	int size = 0;
	bool have_uboot = false;
	int bios_fd;
	char *image;
	int ret;
	static struct option long_options[] = {
		{"create", 0, NULL, 'c'},
		{"dump", 0, NULL, 'd'},
		{"descriptor", 1, NULL, 'D'},
		{"em100", 0, NULL, 'e'},
		{"extract", 0, NULL, 'x'},
		{"fdt", 1, NULL, 'f'},
		{"inject", 1, NULL, 'i'},
		{"lock", 0, NULL, 'l'},
		{"romsize", 1, NULL, 'r'},
		{"spifreq", 1, NULL, 's'},
		{"unlock", 0, NULL, 'u'},
		{"uboot", 1, NULL, 'U'},
		{"write", 1, NULL, 'w'},
		{"version", 0, NULL, 'v'},
		{"help", 0, NULL, 'h'},
		{0, 0, 0, 0}
	};

	while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?",
				  long_options, &option_index)) != EOF) {
		switch (opt) {
		case 'c':
			create = 1;
			break;
		case 'd':
			mode_dump = 1;
			break;
		case 'D':
			mode_write_descriptor = 1;
			desc_fname = optarg;
			break;
		case 'e':
			mode_em100 = 1;
			break;
		case 'i':
			if (get_two_words(optarg, &region_type_string,
					  &inject_fname)) {
				print_usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			if (!strcasecmp("Descriptor", region_type_string))
				region_type = 0;
			else if (!strcasecmp("BIOS", region_type_string))
				region_type = 1;
			else if (!strcasecmp("ME", region_type_string))
				region_type = 2;
			else if (!strcasecmp("GbE", region_type_string))
				region_type = 3;
			else if (!strcasecmp("Platform", region_type_string))
				region_type = 4;
			if (region_type == -1) {
				fprintf(stderr, "No such region type: '%s'\n\n",
					region_type_string);
				print_usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			mode_inject = 1;
			break;
		case 'l':
			mode_locked = 1;
			break;
		case 'r':
			rom_size = strtol(optarg, NULL, 0);
			debug("ROM size %d\n", rom_size);
			break;
		case 's':
			/* Parse the requested SPI frequency */
			inputfreq = strtol(optarg, NULL, 0);
			switch (inputfreq) {
			case 20:
				spifreq = SPI_FREQUENCY_20MHZ;
				break;
			case 33:
				spifreq = SPI_FREQUENCY_33MHZ;
				break;
			case 50:
				spifreq = SPI_FREQUENCY_50MHZ;
				break;
			default:
				fprintf(stderr, "Invalid SPI Frequency: %d\n",
					inputfreq);
				print_usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			mode_spifreq = 1;
			break;
		case 'u':
			mode_unlocked = 1;
			break;
		case 'v':
			print_version();
			exit(EXIT_SUCCESS);
			break;
		case 'w':
		case 'U':
		case 'f':
			ifile = &input_file[wr_num];
			mode_write = 1;
			if (wr_num < WRITE_MAX) {
				if (get_two_words(optarg, &addr_str,
						  &ifile->fname)) {
					print_usage(argv[0]);
					exit(EXIT_FAILURE);
				}
				ifile->addr = strtoll(optarg, NULL, 0);
				wr_num++;
			} else {
				fprintf(stderr,
					"The number of files to write simultaneously exceeds the limitation (%d)\n",
					WRITE_MAX);
			}
			break;
		case 'x':
			mode_extract = 1;
			break;
		case 'h':
		case '?':
		default:
			print_usage(argv[0]);
			exit(EXIT_SUCCESS);
			break;
		}
	}

	if (mode_locked == 1 && mode_unlocked == 1) {
		fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
		exit(EXIT_FAILURE);
	}

	if (mode_inject == 1 && mode_write == 1) {
		fprintf(stderr, "Inject/Write are mutually exclusive\n");
		exit(EXIT_FAILURE);
	}

	if ((mode_dump + mode_extract + mode_inject +
		(mode_spifreq | mode_em100 | mode_unlocked |
		 mode_locked)) > 1) {
		fprintf(stderr, "You may not specify more than one mode.\n\n");
		print_usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
	     mode_em100 + mode_locked + mode_unlocked + mode_write +
	     mode_write_descriptor) == 0 && !create) {
		fprintf(stderr, "You need to specify a mode.\n\n");
		print_usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	if (create && rom_size == -1) {
		fprintf(stderr, "You need to specify a rom size when creating.\n\n");
		exit(EXIT_FAILURE);
	}

	if (optind + 1 != argc) {
		fprintf(stderr, "You need to specify a file.\n\n");
		print_usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	if (have_uboot && !fdt) {
		fprintf(stderr,
			"You must supply a device tree file for U-Boot\n\n");
		print_usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	filename = argv[optind];
	if (optind + 2 != argc)
		outfile = argv[optind + 1];

	if (create)
		bios_fd = open(filename, O_WRONLY | O_CREAT, 0666);
	else
		bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR);

	if (bios_fd == -1) {
		perror("Could not open file");
		exit(EXIT_FAILURE);
	}

	if (!create) {
		if (fstat(bios_fd, &buf) == -1) {
			perror("Could not stat file");
			exit(EXIT_FAILURE);
		}
		size = buf.st_size;
	}

	debug("File %s is %d bytes\n", filename, size);

	if (rom_size == -1)
		rom_size = size;

	image = malloc(rom_size);
	if (!image) {
		printf("Out of memory.\n");
		exit(EXIT_FAILURE);
	}

	memset(image, '\xff', rom_size);
	if (!create && read(bios_fd, image, size) != size) {
		perror("Could not read file");
		exit(EXIT_FAILURE);
	}
	if (size != rom_size) {
		debug("ROM size changed to %d bytes\n", rom_size);
		size = rom_size;
	}

	write_it = true;
	ret = 0;
	if (mode_dump) {
		ret = dump_fd(image, size);
		write_it = false;
	}

	if (mode_extract) {
		ret = write_regions(image, size);
		write_it = false;
	}

	if (mode_write_descriptor)
		ret = write_data(image, size, -size, desc_fname, 0, 0);

	if (mode_inject)
		ret = inject_region(image, size, region_type, inject_fname);

	if (mode_write) {
		int offset_uboot_top = 0;
		int offset_uboot_start = 0;

		for (wr_idx = 0; wr_idx < wr_num; wr_idx++) {
			ifile = &input_file[wr_idx];
			ret = write_data(image, size, ifile->addr,
					 ifile->fname, offset_uboot_top,
					 offset_uboot_start);
			if (ret < 0)
				break;
		}
	}

	if (mode_spifreq)
		set_spi_frequency(image, size, spifreq);

	if (mode_em100)
		set_em100_mode(image, size);

	if (mode_locked)
		lock_descriptor(image, size);

	if (mode_unlocked)
		unlock_descriptor(image, size);

	if (write_it) {
		if (outfile) {
			ret = write_image(outfile, image, size);
		} else {
			if (lseek(bios_fd, 0, SEEK_SET)) {
				perror("Error while seeking");
				ret = -1;
			}
			if (write(bios_fd, image, size) != size) {
				perror("Error while writing");
				ret = -1;
			}
		}
	}

	free(image);
	close(bios_fd);

	return ret < 0 ? 1 : 0;
}