Always generate absolute address for SMBIOS tables (follow the spec).
This is a big re-factoring, which is a following CL after 1243
(see http://gerrit.chromium.org/gerrit/#change,1243).
In CL 1243, Hungte mentioned the case C & D are annoying and suggested to
remove. This CL is going to removed that. So that, when reading file, the vpd
will try 3 ways to get the 'eps_base' value:
1. try to parse fmap structure and get the offset of VPD partition.
2. try to search "_SM_" signature in file.
3. try to load content from BIOS to learn the eps_base.
Alternatively, user can use -E to force the eps_base value.
For the backward-compatible, we keep the ability to read case B. Once a
write is happening on case B, the offset will be corrected to absolute.
Which means following the SMBIOS spec.
Also did some re-factoring to make code more readable and easy to maintain.
BUS=chrome-os-partner:4010
TEST=Tested all commands in CL 1243, and the following commands:
rm -f /tmp/zero ; touch /tmp/zero
vpd -f /tmp/zero -l # loadFile() error
vpd -f /tmp/zero -O # got a 1537-byte file, the eps_base is 0x1f0000.
rm -f /tmp/zero ; touch /tmp/zero
vpd -f /tmp/zero -E 0x230000 -O # a 1537-byte file, and eps_base is 0x230000.
In addition, I write a testing script that runs combinations and corner cases.
I have run that script on K and Z models and passed.
Reviewed-on: http://gerrit.chromium.org/gerrit/1360
Reviewed-by: Yung-Chieh Lo <yjlou%chromium.org@gtempaccount.com>
Tested-by: Yung-Chieh Lo <yjlou%chromium.org@gtempaccount.com>
(cherry picked from commit edca624b92638efb06933a3ab0eb8b38201815ec)
Change-Id: I0704ec32b4d34e00ef038c2cec52603e3f8a36ba
Reviewed-on: http://gerrit.chromium.org/gerrit/2977
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Yung-Chieh Lo <yjlou%chromium.org@gtempaccount.com>
Tested-by: Yung-Chieh Lo <yjlou%chromium.org@gtempaccount.com>
diff --git a/include/lib/flashrom.h b/include/lib/flashrom.h
index c4268c9..7828160 100644
--- a/include/lib/flashrom.h
+++ b/include/lib/flashrom.h
@@ -33,8 +33,10 @@
FLASHROM_FAIL,
};
-int flashromRead(const char* part_file, const char* full_file,
- const char* partition_name);
+int flashromFullRead(const char* full_file);
+
+int flashromPartialRead(const char* part_file, const char* full_file,
+ const char* partition_name);
int flashromPartialWrite(const char* part_file, const char* full_file,
const char* partition_name);
diff --git a/include/lib/fmap.h b/include/lib/fmap.h
index cf0955f..d7f1b24 100644
--- a/include/lib/fmap.h
+++ b/include/lib/fmap.h
@@ -122,7 +122,7 @@
*
*/
int fmapGetArea(const char *name, const struct fmap *fmap,
- off_t *offset, off_t *size);
+ uint32_t *offset, uint32_t *size);
#endif /* __LIB_FMAP_H__*/
diff --git a/include/lib/vpd.h b/include/lib/vpd.h
index cd18d61..520d688 100644
--- a/include/lib/vpd.h
+++ b/include/lib/vpd.h
@@ -30,16 +30,6 @@
VPD_TYPE_BINARY_BLOB_POINTER = 241,
};
-/* The default RO VPD location in BIOS image.
- * If VPD partition cannot be found on fmap, buildEpsAndTables() will use
- * this value to count the offset fields of SPD and VPD 2.0.
- * User can specify -E argument to change the EPS base value.
- */
-#define GOOGLE_EPS_BASE 0xFFFFFFFF
-/* 0xFFFFFFFF is a special value, which is the value of a blank flash.
- * It means we don't know the eps->table_address.
- * This usually happens when we are creating a new VPD partition without
- * knowing the flash topology (fmap). */
#define GOOGLE_SPD_OFFSET 0x400
#define GOOGLE_SPD_UUID "75f4926b-9e43-4b32-8979-eb20c0eda76a"
diff --git a/lib/flashrom.c b/lib/flashrom.c
index 2a3a3f3..88b17a2 100644
--- a/lib/flashrom.c
+++ b/lib/flashrom.c
@@ -42,12 +42,26 @@
*/
static uint8_t flashrom_arguments[] = " -p internal:bus=spi ";
-int flashromRead(const char* part_file, const char* full_file,
- const char* partition_name) {
+int flashromFullRead(const char* full_file) {
char cmd[CMD_BUF_SIZE];
int ret = 0;
- snprintf(cmd, sizeof(cmd), "%s %s -i '%s':'%s' -r '%s' >/dev/null 2>&1",
+ snprintf(cmd, sizeof(cmd), "%s %s -r '%s' >/dev/null 2>&1",
+ flashrom_cmd, flashrom_arguments, full_file);
+ ret = system(cmd);
+ if (ret == 0)
+ return FLASHROM_OK;
+ else
+ return FLASHROM_FAIL;
+}
+
+int flashromPartialRead(const char* part_file, const char* full_file,
+ const char* partition_name) {
+ char cmd[CMD_BUF_SIZE];
+ int ret = 0;
+
+ snprintf(cmd, sizeof(cmd), "%s %s -i FMAP -i '%s':'%s' "
+ "-r '%s' >/dev/null 2>&1",
flashrom_cmd, flashrom_arguments,
partition_name, part_file, full_file);
ret = system(cmd);
diff --git a/lib/fmap.c b/lib/fmap.c
index 15f0172..2544aea 100644
--- a/lib/fmap.c
+++ b/lib/fmap.c
@@ -87,7 +87,7 @@
* TODO: need more sanity check for fmap.
*/
int fmapGetArea(const char *name, const struct fmap *fmap,
- off_t *offset, off_t *size) {
+ uint32_t *offset, uint32_t *size) {
int i;
assert(offset);
diff --git a/vpd.c b/vpd.c
index 2c77bb9..1262cc7 100644
--- a/vpd.c
+++ b/vpd.c
@@ -65,7 +65,8 @@
*
* User can overwrite this by -E argument.
*/
-uint32_t eps_base = GOOGLE_EPS_BASE;
+#define UNKNOWN_EPS_BASE ((uint32_t)-1)
+uint32_t eps_base = UNKNOWN_EPS_BASE;
int eps_base_force_specified = 0; /* a bool value to indicate if -E argument
* is given. */
@@ -83,7 +84,6 @@
* SPD
* VPD 2.0 data
*
- * For those offset values below, ABSENT means not presented in buffer.
*/
uint32_t vpd_offset = 0, vpd_size; /* The whole partition */
/* Below offset are related to vpd_offset and assume positive.
@@ -98,15 +98,15 @@
uint8_t *spd_data = NULL;
int32_t spd_len = 256; /* max value for DDR3 */
-/* for debug purpose */
-void dumpBuf() {
- int i;
- for(i = 0; i < buf_len; ++i) {
- printf("%02x ", buf[i]);
- if ((i % 16) == 15) printf("\n");
- }
-}
+int myMkTemp(uint8_t *tmp_file) {
+ int fd;
+ fd = mkstemp(tmp_file);
+ if (fd < 0) {
+ fprintf(stderr, "mkstemp(%s) failed\n", tmp_file);
+ }
+ return fd;
+}
/* Given the offset of blob block (related to the first byte of EPS) and
* the size of blob, the is function generates an SMBIOS ESP.
@@ -124,6 +124,7 @@
assert(buf);
assert(generated);
+ assert(eps_base != UNKNOWN_EPS_BASE);
buf += *generated;
@@ -215,69 +216,140 @@
}
-/*
- * The SMBIOS requires the offset in type 241 table is absolute address.
- * We get in trouble if only VPD partition is read from BIOS (for speed)
- * because we have no overview scope to know the absolute address in BIOS.
- *
- * The below table shows the conditions we do/don't know the actual table
- * address. Case A&B are determined. We need to make assumption in case C&D.
- *
- * \ | |
- * \ table made by | vpd -f | vpd (via flashrom
- * \____________ | | partial read/write)
- * how it is \ | data->offset = | data->offset =
- * read this time \ | 0x1f0600 | 0x5ff
- * -------------------+----------------+----------------------
- * we have full image| data->offset - | data->offset -
- * eps_base = | eps_base | GOOGLE_EPS_BASE
- * 0x1f0000 | = 0x600 (A)| = 0x600 (B)
- * -------------------+----------------+----------------------
- * got partial image | we assume EPS | data->offset -
- * eps_base = | starts at 64KB | GOOGLE_EPS_BASE
- * GOOGLE_EPS_BASE| boundary. (C)| = 0x600 (D)
- * | |
- *
- * Note that: GOOGLE_EPS_BASE is -1 (0xFFFFFFFF).
- * eps_base 0x1f0xxx is just example. Real value is saved in fmap.
- */
-static uint32_t guess_offset(uint32_t data_offset, uint32_t eps_base) {
- if (eps_base != GOOGLE_EPS_BASE) {
- if (data_offset > eps_base) {
- /* case A */
- return data_offset - eps_base;
- } else {
- /* case B */
- return data_offset - GOOGLE_EPS_BASE;
- }
- } else {
- const uint32_t assumed_partition_size = 1 << 16; /* 64KB */
- const uint32_t table_alignment = 0x100; /* 256B */
- uint32_t offset;
+/* Given an address, compare if it is SMBIOS signature ("_SM_"). */
+int isEps(const void* ptr) {
+ return !memcmp(VPD_ENTRY_MAGIC, ptr, sizeof(VPD_ENTRY_MAGIC) - 1);
+ /* TODO(yjlou): need more EPS sanity checks here. */
+}
- if (!(data_offset & (table_alignment - 1))) {
- /* case C */
- offset = data_offset & (assumed_partition_size - 1);
- fprintf(stderr, "[WARN] case C, guess table offset 0x%0x.\n", offset);
- } else {
- /* case D */
- offset = data_offset - GOOGLE_EPS_BASE;
- fprintf(stderr, "[WARN] case D, guess table offset 0x%0x.\n", offset);
+
+/* There are two possible file content appearng here:
+ * 1. a full and complete BIOS file
+ * 2. a full but only VPD partition area is valid. (no fmap)
+ * 3. a full BIOS, but VPD partition is blank.
+ *
+ * The first case is easy. Just lookup the fmap and find out the VPD partition.
+ * The second is harder. We try to search the SMBIOS signature (since others
+ * are blank). For the third, we just return and leave caller to read full
+ * content, including fmap info.
+ *
+ * If found, vpd_offset and vpd_size are updated.
+ */
+int findVpdPartition(const uint8_t* read_buf, const uint32_t file_size,
+ uint32_t* vpd_offset, uint32_t* vpd_size) {
+ off_t sig_offset;
+ struct fmap *fmap;
+ int i;
+
+ assert(read_buf);
+ assert(vpd_offset);
+ assert(vpd_size);
+
+ /* scan the file and find out the VPD partition. */
+ sig_offset = fmapFind(read_buf, file_size);
+ if (-1 != sig_offset) {
+ /* FMAP signature is found, try to search the partition name in table. */
+ fmap = (struct fmap *)&read_buf[sig_offset];
+ for(i = 0; i < fmap->nareas; i++) {
+ fmapNormalizeAreaName(fmap->areas[i].name);
}
- return offset;
+
+ if (FMAP_OK == fmapGetArea(fmap_vpd_area_name, fmap,
+ vpd_offset, vpd_size)) {
+ found_vpd = 1; /* Mark found here then saveFile() knows where to
+ * write back (vpd_offset, vpd_size). */
+ return 0;
+ } else {
+ fprintf(stderr, "[ERROR] The VPD partition [%s] is not found.\n",
+ fmap_vpd_area_name);
+ return 1;
+ }
}
+
+ /* The signature must be aligned to 16-byte. */
+ for (i = 0; i < file_size; i += 16) {
+ if (isEps(&read_buf[i])) {
+ found_vpd = 1; /* Mark found here then saveFile() knows where to
+ * write back (vpd_offset, vpd_size). */
+ *vpd_offset = i;
+ /* FIXME: We don't know the VPD partition size in this case.
+ * However, return 4K should be safe enough now.
+ * In the long term, this code block will be obscured. */
+ *vpd_size = 4096;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/* Load file content into memory.
+ * Returns: NULL if file opens error or read error.
+ * Others, pointer to the memory. The filesize is also returned.
+ *
+ * Note: it's caller's responsbility to free the memory.
+ */
+uint8_t *readFileContent(const char* filename, uint32_t *filesize) {
+ FILE *fp;
+ uint8_t *read_buf;
+
+ assert(filename);
+ assert(filesize);
+
+ if (!(fp = fopen(filename, "r"))) {
+ return NULL;
+ }
+ /* get file size */
+ fseek(fp, 0, SEEK_END);
+ *filesize = ftell(fp);
+
+ /* read file content */
+ fseek(fp, 0, SEEK_SET);
+ read_buf = malloc(*filesize);
+ assert(read_buf);
+ if (*filesize != fread(read_buf, 1, *filesize, fp)) {
+ fprintf(stderr, "[ERROR] Reading file [%s] failed.\n", filename);
+ return NULL;
+ }
+ fclose(fp);
+
+ return read_buf;
+}
+
+
+int getVpdPartitionFromFullBios(uint32_t* offset, uint32_t* size) {
+ uint8_t filename[] = "/tmp/vpd.flashrom.XXXXXX";
+ uint8_t *buf;
+ uint32_t buf_size;
+ int retval;
+
+ if (myMkTemp(filename) < 0) {
+ return 1;
+ }
+
+ if (FLASHROM_OK != flashromFullRead(filename)) {
+ fprintf(stderr, "[WARN] Cannot read full BIOS.\n");
+ return 1;
+ }
+ assert(buf = readFileContent(filename, &buf_size));
+ if (findVpdPartition(buf, buf_size, offset, size)) {
+ fprintf(stderr, "[WARN] Cannot get eps_base from full BIOS.\n");
+ retval = 1;
+ } else {
+ retval = 0;
+ }
+ free(buf);
+ return retval;
}
int loadFile(const char *filename, struct PairContainer *container,
int overwrite_it) {
- FILE *fp;
uint32_t file_size;
uint8_t *read_buf;
- off_t sig_offset;
- struct fmap *fmap;
uint8_t *vpd_buf;
struct vpd_entry *eps;
+ uint32_t related_eps_base;
struct vpd_header *header;
struct vpd_table_binary_blob_pointer *data;
uint8_t spd_uuid[16], vpd_2_0_uuid[16];
@@ -286,88 +358,76 @@
int index;
int retval = 0;
- if (!(fp = fopen(filename, "r"))) {
- fprintf(stderr, "[WARN] File [%s] cannot be opened for read. It's fine.\n",
- filename);
+ if (!(read_buf = readFileContent(filename, &file_size))) {
+ fprintf(stderr, "[WARN] Cannot LoadFile('%s'), that's fine.\n", filename);
return 0;
}
- /* get file size */
- fseek(fp, 0, SEEK_END);
- file_size = ftell(fp);
- /* read file content */
- fseek(fp, 0, SEEK_SET);
- read_buf = malloc(file_size);
- assert(read_buf);
- if (file_size != fread(read_buf, 1, file_size, fp)) {
- fprintf(stderr, "Reading file [%s] failed.\n", filename);
+ if (0 == findVpdPartition(read_buf, file_size, &vpd_offset, &vpd_size)) {
+ if (!eps_base_force_specified) {
+ eps_base = vpd_offset;
+ }
+ } else {
+ /* We cannot parse out the VPD partition address from given file.
+ * Then, try to read the whole BIOS chip. */
+ uint32_t offset, size;
+ if (!eps_base_force_specified) {
+ if (0 == getVpdPartitionFromFullBios(&offset, &size)) {
+ eps_base = offset;
+ vpd_size = size;
+ } else {
+ if (overwrite_it) {
+ retval = 0;
+ } else {
+ fprintf(stderr, "[ERROR] getVpdPartitionFromFullBios() failed.");
+ retval = 1;
+ }
+ goto teardown;
+ }
+ }
+ }
+
+ /* Update the following variables:
+ * eps_base: integer, the VPD EPS address in ROM.
+ * vpd_offset: integer, the VPD partition offset in file (read_buf[]).
+ * vpd_buf: uint8_t*, points to the VPD partition.
+ * eps: vpd_entry*, points to the EPS structure.
+ * eps_offset: integer, the offset of EPS related to vpd_buf[].
+ */
+ vpd_buf = &read_buf[vpd_offset];
+ /* eps and eps_offset will be set slightly later. */
+
+ if (eps_base == UNKNOWN_EPS_BASE) {
+ fprintf(stderr, "[ERROR] Cannot determine eps_base. Cannot go on.\n"
+ " You may use -E to specify the value.\n");
retval = 1;
goto teardown;
}
- fclose(fp);
- /* scan the file and find out the VPD partition. */
- sig_offset = fmapFind(read_buf, file_size);
- if (-1 == sig_offset) {
- /* FMAP signature is not found, assume it is pure VPD partition. */
- vpd_buf = read_buf;
- eps = (struct vpd_entry *)vpd_buf;
+ /* In overwrite mode, we don't care the content inside. Stop parsing. */
+ if (overwrite_it) {
+ retval = 0;
+ goto teardown;
+ }
- /* In overwrite mode, ignore all existing data. */
- if (overwrite_it) {
- retval = 0;
- goto teardown;
- }
- } else {
- /* FMAP signature is found, try to search the partition name in table. */
- int i;
-
- fmap = (struct fmap *)&read_buf[sig_offset];
- for(i = 0; i < fmap->nareas; i++) {
- fmapNormalizeAreaName(fmap->areas[i].name);
- }
-
- if (FMAP_OK == fmapGetArea(fmap_vpd_area_name, fmap,
- &vpd_offset, &vpd_size)) {
- found_vpd = 1; /* Mark found here then saveFile() knows where to
- * write back (vpd_offset, vpd_size). */
- eps_base = vpd_offset;
- vpd_buf = &read_buf[vpd_offset];
- eps = (struct vpd_entry *)vpd_buf;
-
- /* In overwrite mode, the VPD content is erased before reading. */
- if (overwrite_it) {
- retval = 0;
- goto teardown;
- }
- } else {
- fprintf(stderr, "The VPD partition [%s] is not found.\n",
- fmap_vpd_area_name);
- retval = 1;
- goto teardown;
+ if (vpd_size < sizeof(struct vpd_entry)) {
+ fprintf(stderr, "[ERROR] vpd_size:%d is too small to be compared.\n",
+ vpd_size);
+ retval = 1;
+ goto teardown;
+ }
+ /* try to search the EPS if it is not aligned to the begin of partition. */
+ for (index = 0; index < vpd_size; index += 16) {
+ if (isEps(&vpd_buf[index])) {
+ eps = (struct vpd_entry *)&vpd_buf[index];
+ eps_offset = index;
+ break;
}
}
- /* Now, vpd_buf points to the VPD partition in buffer.
- * eps points to the EPS structure, which is usually equal to vpd_buf. */
- eps_offset = (uint8_t*)eps - vpd_buf;
-
- /* check if ups_base variable needs to be updated. */
- if (!eps_base_force_specified) {
- if (eps->table_address > file_size) {
- /* If the table address field of EPS indicates the position exceeding
- * the file size, that means some how this field needs to be shifted.
- * A special case is 0xFFFFFFFF, which means unkowns address. But this
- * is okay because the later offset of structure table are counted
- * related to this value. */
- eps_base = eps->table_address - sizeof(*eps);
- fprintf(stderr, "[INFO] we guess eps_base is 0x%x.\n", eps_base);
- }
- }
-
/* jump if the VPD partition is not recognized. */
- if (memcmp(VPD_ENTRY_MAGIC, eps, sizeof(VPD_ENTRY_MAGIC) - 1)) {
- /* But OKAY if the VPD partition is all-FF, which is un-used. */
- if (!memcmp("\xff\xff\xff\xff", eps, sizeof(VPD_ENTRY_MAGIC) - 1)) {
+ if (index >= vpd_size) {
+ /* But OKAY if the VPD partition starts with FF, which might be un-used. */
+ if (!memcmp("\xff\xff\xff\xff", vpd_buf, sizeof(VPD_ENTRY_MAGIC) - 1)) {
fprintf(stderr, "[WARN] VPD partition not formatted. It's fine.\n");
retval = 0;
goto teardown;
@@ -377,8 +437,15 @@
retval = 1;
goto teardown;
}
- /* TODO(yjlou): need more EPS sanity checks here. */
}
+
+ /* adjust the eps_base for data->offset field below. */
+ if (!eps_base_force_specified) {
+ related_eps_base = eps->table_address - sizeof(*eps);
+ } else {
+ related_eps_base = eps_base;
+ }
+
/* EPS is done above. Parse structure tables below. */
/* Get the first type 241 blob, at the tail of EPS. */
header = (struct vpd_header*)(((uint8_t*)eps) + eps->entry_length);
@@ -410,7 +477,7 @@
uuid_parse(GOOGLE_SPD_UUID, spd_uuid);
if (!memcmp(data->uuid, spd_uuid, sizeof(data->uuid))) {
++expected_handle;
- spd_offset = guess_offset(data->offset, eps_base);
+ spd_offset = data->offset - related_eps_base;
spd_len = data->size;
if (vpd_offset + spd_offset + spd_len >= file_size) {
fprintf(stderr, "[ERROR] SPD offset in BBP is not correct.\n"
@@ -454,7 +521,7 @@
++expected_handle;
/* iterate all pairs */
- for (index = guess_offset(data->offset, eps_base); /* skip the EPS */
+ for (index = data->offset - related_eps_base; /* skip the EPS */
vpd_buf[index] != VPD_TYPE_TERMINATOR &&
vpd_buf[index] != VPD_TYPE_IMPLICIT_TERMINATOR;) {
if (VPD_OK != decodeVpdString(file_size, vpd_buf, container, &index)) {
@@ -490,11 +557,13 @@
}
-int saveFile(const struct PairContainer *container, const char *filename) {
+int saveFile(const struct PairContainer *container, const char *filename,
+ int write_back_to_flash) {
FILE *fp;
unsigned char eps[1024];
int eps_len = 0;
int retval = 0;
+ uint32_t file_seek;
memset(eps, 0xff, sizeof(eps));
@@ -540,8 +609,14 @@
}
}
+ if (write_back_to_flash) {
+ file_seek = 0;
+ } else {
+ file_seek = vpd_offset;
+ }
+
/* write EPS */
- fseek(fp, vpd_offset + eps_offset, SEEK_SET);
+ fseek(fp, file_seek + eps_offset, SEEK_SET);
if (fwrite(eps, eps_len, 1, fp) != 1) {
fprintf(stderr, "fwrite(EPS) error (%s)\n", strerror(errno));
retval = 1;
@@ -550,7 +625,7 @@
/* write SPD */
if (spd_data) {
- fseek(fp, vpd_offset + spd_offset, SEEK_SET);
+ fseek(fp, file_seek + spd_offset, SEEK_SET);
if (fwrite(spd_data, spd_len, 1, fp) != 1) {
fprintf(stderr, "fwrite(SPD) error (%s)\n", strerror(errno));
retval = 1;
@@ -559,7 +634,7 @@
}
/* write VPD 2.0 */
- fseek(fp, vpd_offset + vpd_2_0_offset, SEEK_SET);
+ fseek(fp, file_seek + vpd_2_0_offset, SEEK_SET);
if (fwrite(buf, buf_len, 1, fp) != 1) {
fprintf(stderr, "fwrite(VPD 2.0) error (%s)\n", strerror(errno));
retval = 1;
@@ -571,15 +646,6 @@
return retval;
}
-int myMkTemp(uint8_t *tmp_file) {
- int fd;
- fd = mkstemp(tmp_file);
- if (fd < 0) {
- fprintf(stderr, "mkstemp(%s) failed\n", tmp_file);
- }
- return fd;
-}
-
int generateTempFilenames(void) {
if (myMkTemp(tmp_part_file) < 0) return -1;
if (myMkTemp(tmp_full_file) < 0) return -1;
@@ -624,6 +690,8 @@
{0, 0, 0, 0}
};
char *filename = NULL;
+ char *load_file = NULL;
+ char *save_file = NULL;
char *filter_str = NULL;
int write_back_to_flash = 0;
int list_it = 0;
@@ -733,18 +801,23 @@
/* if no filename is specified, call flashrom to read from flash. */
if (!filename) {
- if (FLASHROM_OK != flashromRead(tmp_part_file, tmp_full_file,
- fmap_vpd_area_name)) {
- fprintf(stderr, "flashromRead() error!\n");
+ if (FLASHROM_OK != flashromPartialRead(tmp_part_file, tmp_full_file,
+ fmap_vpd_area_name)) {
+ fprintf(stderr, "flashromPartialRead() error!\n");
retval = 1;
goto teardown;
}
+
write_back_to_flash = 1;
- filename = strdup(tmp_part_file);
+ load_file = tmp_full_file;
+ save_file = tmp_part_file;
+ } else {
+ load_file = filename;
+ save_file = filename;
}
- if (retval = loadFile(filename, &file, overwrite_it)) {
- fprintf(stderr, "loadFile('%s') error.\n", filename);
+ if (retval = loadFile(load_file, &file, overwrite_it)) {
+ fprintf(stderr, "loadFile('%s') error.\n", load_file);
goto teardown;
}
@@ -768,13 +841,13 @@
}
if (modified) {
- if (retval = saveFile(&file, filename)) {
+ if (retval = saveFile(&file, save_file, write_back_to_flash)) {
fprintf(stderr, "saveFile('%s') error.\n", filename);
goto teardown;
}
if (write_back_to_flash) {
- if (FLASHROM_OK != flashromPartialWrite(filename, tmp_full_file,
+ if (FLASHROM_OK != flashromPartialWrite(save_file, tmp_full_file,
fmap_vpd_area_name)) {
fprintf(stderr, "flashromPartialWrite() error.\n");
retval = 1;