+// SPDX-License-Identifier: GPL-2.0
/*
* ifdtool - Manage Intel Firmware Descriptor information
*
* Copyright 2014 Google, Inc
*
- * SPDX-License-Identifier: GPL-2.0
- *
* From Coreboot project, but it got a serious code clean-up
* and a few new features
*/
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <linux/libfdt.h>
#include "ifdtool.h"
#undef DEBUG
#define FLREG_BASE(reg) ((reg & 0x00000fff) << 12);
#define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff);
+struct input_file {
+ char *fname;
+ unsigned int addr;
+};
+
/**
* find_fd() - Find the flash description in the ROM image
*
return NULL;
}
- debug("Found Flash Descriptor signature at 0x%08x\n", i);
+ debug("Found Flash Descriptor signature at 0x%08lx\n",
+ (char *)ptr - image);
return (struct fdbar_t *)ptr;
}
if (ret)
return ret;
dump_region(i, frba);
- if (region.size == 0)
+ if (region.size <= 0)
continue;
region_fd = open(region_filename(i),
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
return ret;
}
+static int perror_fname(const char *fmt, const char *fname)
+{
+ char msg[strlen(fmt) + strlen(fname) + 1];
+
+ sprintf(msg, fmt, fname);
+ perror(msg);
+
+ return -1;
+}
+
/**
* write_image() - Write the image to a file
*
new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
S_IWUSR | S_IRGRP | S_IROTH);
- if (write(new_fd, image, size) != size) {
- perror("Error while writing");
- return -1;
- }
+ if (new_fd < 0)
+ return perror_fname("Could not open file '%s'", filename);
+ if (write(new_fd, image, size) != size)
+ return perror_fname("Could not write file '%s'", filename);
close(new_fd);
return 0;
int fd = open(fname, O_RDONLY);
struct stat buf;
- if (fd == -1) {
- perror("Could not open file");
- return -1;
- }
- if (fstat(fd, &buf) == -1) {
- perror("Could not stat file");
- return -1;
- }
+ if (fd == -1)
+ return perror_fname("Could not open file '%s'", fname);
+ if (fstat(fd, &buf) == -1)
+ return perror_fname("Could not stat file '%s'", fname);
*sizep = buf.st_size;
debug("File %s is %d bytes\n", fname, *sizep);
* 0xffffffff so use an address relative to that. For an
* 8MB ROM the start address is 0xfff80000.
* @write_fname: Filename to add to the image
- * @return 0 if OK, -ve on error
+ * @offset_uboot_top: Offset of the top of U-Boot
+ * @offset_uboot_start: Offset of the start of U-Boot
+ * @return number of bytes written if OK, -ve on error
*/
static int write_data(char *image, int size, unsigned int addr,
- const char *write_fname)
+ const char *write_fname, int offset_uboot_top,
+ int offset_uboot_start)
{
int write_fd, write_size;
int offset;
if (write_fd < 0)
return write_fd;
- offset = addr + size;
+ offset = (uint32_t)(addr + size);
+ if (offset_uboot_top) {
+ if (offset_uboot_start < offset &&
+ offset_uboot_top >= offset) {
+ fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
+ write_fname);
+ fprintf(stderr,
+ "U-Boot finishes at offset %x, file starts at %x\n",
+ offset_uboot_top, offset);
+ return -EXDEV;
+ }
+ if (offset_uboot_start > offset &&
+ offset_uboot_start <= offset + write_size) {
+ fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
+ write_fname);
+ fprintf(stderr,
+ "U-Boot starts at offset %x, file finishes at %x\n",
+ offset_uboot_start, offset + write_size);
+ return -EXDEV;
+ }
+ }
debug("Writing %s to offset %#x\n", write_fname, offset);
if (offset < 0 || offset + write_size > size) {
close(write_fd);
- return 0;
+ return write_size;
}
static void print_version(void)
{
printf("ifdtool v%s -- ", IFDTOOL_VERSION);
printf("Copyright (C) 2014 Google Inc.\n\n");
- printf("SPDX-License-Identifier: GPL-2.0+\n");
+ printf("SPDX-License-Identifier: GPL-2.0+\n");
}
static void print_usage(const char *name)
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, *src_fname = NULL;
- char *addr_str = NULL;
+ 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;
- unsigned int addr[WRITE_MAX];
- char *wr_fname[WRITE_MAX];
+ 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 *outfile = NULL;
struct stat buf;
int size = 0;
+ bool have_uboot = false;
int bios_fd;
char *image;
int ret;
{"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:ehi:lr:s:uvw:x?",
+ while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'c':
break;
case 'D':
mode_write_descriptor = 1;
- src_fname = optarg;
+ desc_fname = optarg;
break;
case 'e':
mode_em100 = 1;
break;
case 'i':
if (get_two_words(optarg, ®ion_type_string,
- &src_fname)) {
+ &inject_fname)) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
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,
- &wr_fname[wr_num])) {
+ &ifile->fname)) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
- addr[wr_num] = strtol(optarg, NULL, 0);
+ ifile->addr = strtoll(optarg, NULL, 0);
wr_num++;
} else {
fprintf(stderr,
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 (mode_write_descriptor)
- ret = write_data(image, size, -size, src_fname);
+ ret = write_data(image, size, -size, desc_fname, 0, 0);
if (mode_inject)
- ret = inject_region(image, size, region_type, src_fname);
+ 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++) {
- ret = write_data(image, size,
- addr[wr_idx], wr_fname[wr_idx]);
- if (ret)
+ ifile = &input_file[wr_idx];
+ ret = write_data(image, size, ifile->addr,
+ ifile->fname, offset_uboot_top,
+ offset_uboot_start);
+ if (ret < 0)
break;
}
}
free(image);
close(bios_fd);
- return ret ? 1 : 0;
+ return ret < 0 ? 1 : 0;
}