| Index: vpd.c
|
| diff --git a/vpd.c b/vpd.c
|
| index 45fbc1d66d319feb170e26c6ff25190a28961725..11787ead340c9ef98591245a29af8c85ce895ba0 100644
|
| --- a/vpd.c
|
| +++ b/vpd.c
|
| @@ -34,7 +34,12 @@
|
| /* The buffer length. Right now the VPD partition size on flash is 128KB. */
|
| #define BUF_LEN (128 * 1024)
|
|
|
| -static uint8_t flashrom_tmp_file[] = "/tmp/vpd.flashrom.XXXXXX";
|
| +/* temp filename for partial read area. */
|
| +static uint8_t tmp_part_file[] = "/tmp/vpd.flashrom.XXXXXX";
|
| +/* temp filename for the full flash content (actually only partial content
|
| + * is available). But for flashrom -w to match flash size, we need to keep this
|
| + * file from flashromRead() to writeFlashrom(). */
|
| +static uint8_t tmp_full_file[] = "/tmp/vpd.flashrom.XXXXXX";
|
|
|
| /* 2 containers:
|
| * file: stores decoded pairs from file.
|
| @@ -61,9 +66,11 @@ int max_buf_len = sizeof(buf);
|
| * User can overwrite this by -E argument.
|
| */
|
| uint32_t eps_base = GOOGLE_EPS_BASE;
|
| +int eps_base_force_specified = 0; /* a bool value to indicate if -E argument
|
| + * is given. */
|
|
|
| /* the fmap name of VPD. */
|
| -uint8_t fmap_vpd_area_name[FMAP_STRLEN] = "RO VPD";
|
| +uint8_t fmap_vpd_area_name[FMAP_STRLEN] = "RO_VPD";
|
|
|
| /* If found_vpd, replace the VPD partition when saveFile().
|
| * If not found, always create new file when saveFlie(). */
|
| @@ -226,7 +233,7 @@ int loadFile(const char *filename, struct PairContainer *container,
|
| int retval = 0;
|
|
|
| if (!(fp = fopen(filename, "r"))) {
|
| - fprintf(stderr, "[WARN] File [%s] cannot be opened for read. Ignored.\n",
|
| + fprintf(stderr, "[WARN] File [%s] cannot be opened for read. It's fine.\n",
|
| filename);
|
| return 0;
|
| }
|
| @@ -258,6 +265,7 @@ int loadFile(const char *filename, struct PairContainer *container,
|
| goto teardown;
|
| }
|
| } else {
|
| + /* FMAP signature is found, try to search the partition name in table. */
|
| int i;
|
|
|
| fmap = (struct fmap *)&read_buf[sig_offset];
|
| @@ -289,10 +297,27 @@ int loadFile(const char *filename, struct PairContainer *container,
|
| * 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 (!memcmp("\xff\xff\xff\xff", eps, sizeof(VPD_ENTRY_MAGIC) - 1)) {
|
| + fprintf(stderr, "[WARN] VPD partition not formatted. It's fine.\n");
|
| + retval = 0;
|
| + goto teardown;
|
| + } else {
|
| fprintf(stderr, "SMBIOS signature is not matched.\n");
|
| fprintf(stderr, "You may use -O to overwrite the data.\n");
|
| retval = 1;
|
| @@ -315,7 +340,8 @@ int loadFile(const char *filename, struct PairContainer *container,
|
| /* Now header points to the first SMBIOS entry, and data points to the
|
| * first BBP entry. The first entry could be SPD data. We don't care. */
|
| if (header->handle != expected_handle) {
|
| - fprintf(stderr, "The first handle value must be 0, but is %d.\n",
|
| + fprintf(stderr, "[ERROR] The first handle value must be 0, but is %d.\n"
|
| + " Use -O option to re-format.\n",
|
| header->handle);
|
| retval = 1;
|
| goto teardown;
|
| @@ -362,7 +388,8 @@ int loadFile(const char *filename, struct PairContainer *container,
|
|
|
| /* The 2nd could be VPD 2.0 data or End Of Table. */
|
| if (header->handle != expected_handle) {
|
| - fprintf(stderr, "The second handle value must be 1, but is %d.\n",
|
| + fprintf(stderr, "[ERROR] The second handle value must be 1, but is %d.\n"
|
| + " Use -O option to re-format.\n",
|
| header->handle);
|
| retval = 1;
|
| goto teardown;
|
| @@ -399,7 +426,7 @@ int loadFile(const char *filename, struct PairContainer *container,
|
| }
|
|
|
| if (header->type != VPD_TYPE_END) {
|
| - fprintf(stderr, "[WARN] we expect the last one is type 127. Ignored.\n");
|
| + fprintf(stderr, "[WARN] we expect the last one is type 127. It's fine.\n");
|
| }
|
|
|
| teardown:
|
| @@ -415,7 +442,7 @@ int saveFile(const struct PairContainer *container, const char *filename) {
|
| int eps_len = 0;
|
| int retval = 0;
|
|
|
| - memset(eps, 0, sizeof(eps));
|
| + memset(eps, 0xff, sizeof(eps));
|
|
|
| /* encode into buffer */
|
| if (VPD_OK != encodeContainer(&file, max_buf_len, buf, &buf_len)) {
|
| @@ -490,6 +517,20 @@ teardown:
|
| 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;
|
| + return 0;
|
| +}
|
|
|
| static void usage(const char *progname) {
|
| printf("Chrome OS VPD 2.0 utility --\n");
|
| @@ -551,6 +592,7 @@ int main(int argc, char *argv[]) {
|
| case 'E':
|
| errno = 0;
|
| eps_base = strtoul(optarg, (char **) NULL, 0);
|
| + eps_base_force_specified = 1;
|
|
|
| /* FIXME: this is not a stable way to detect error because
|
| * implementation may (or may not) assign errno. */
|
| @@ -605,9 +647,14 @@ int main(int argc, char *argv[]) {
|
| }
|
| }
|
|
|
| - fd = mkstemp(flashrom_tmp_file);
|
| - if (fd < 0) {
|
| - fprintf(stderr, "mkstemp(%s) failed\n", flashrom_tmp_file);
|
| + if (optind < argc) {
|
| + fprintf(stderr, "[ERROR] unexpected argument: %s\n\n", argv[optind]);
|
| + usage(argv[0]);
|
| + retval = 1;
|
| + goto teardown;
|
| + }
|
| +
|
| + if (generateTempFilenames() < 0) {
|
| retval = 1;
|
| goto teardown;
|
| }
|
| @@ -617,13 +664,14 @@ int main(int argc, char *argv[]) {
|
|
|
| /* if no filename is specified, call flashrom to read from flash. */
|
| if (!filename) {
|
| - if (FLASHROM_OK != flashromRead(flashrom_tmp_file)) {
|
| + if (FLASHROM_OK != flashromRead(tmp_part_file, tmp_full_file,
|
| + fmap_vpd_area_name)) {
|
| fprintf(stderr, "flashromRead() error!\n");
|
| retval = 1;
|
| goto teardown;
|
| }
|
| write_back_to_flash = 1;
|
| - filename = strdup(flashrom_tmp_file);
|
| + filename = strdup(tmp_part_file);
|
| }
|
|
|
| if (retval = loadFile(filename, &file, overwrite_it)) {
|
| @@ -655,7 +703,8 @@ int main(int argc, char *argv[]) {
|
| }
|
|
|
| if (write_back_to_flash) {
|
| - if (FLASHROM_OK != flashromPartialWrite(filename, vpd_offset, vpd_size)) {
|
| + if (FLASHROM_OK != flashromPartialWrite(filename, tmp_full_file,
|
| + fmap_vpd_area_name)) {
|
| fprintf(stderr, "flashromPartialWrite() error.\n");
|
| retval = 1;
|
| goto teardown;
|
|
|