<p>Marcello Sylvester Bauer has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25615">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">util/vpd/: Add VPD tools<br><br>Add the VPD tools from the ChromiumOS project.<br>https://chromium.googlesource.com/chromiumos/platform/vpd<br><br>Change-Id: Ib3b8de7d27236f3f0e216d5517da0c1f00682f52<br>Signed-off-by: Marcello Sylvester Bauer <info@marcellobauer.com><br>---<br>A util/vpd/LICENSE<br>A util/vpd/Makefile<br>A util/vpd/README.md<br>A util/vpd/include/lib/flashrom.h<br>A util/vpd/include/lib/fmap.h<br>A util/vpd/include/lib/lib_smbios.h<br>A util/vpd/include/lib/lib_vpd.h<br>A util/vpd/include/lib/math.h<br>A util/vpd/include/lib/vpd.h<br>A util/vpd/include/lib/vpd_tables.h<br>A util/vpd/lib/flashrom.c<br>A util/vpd/lib/fmap.c<br>A util/vpd/lib/lib_smbios.c<br>A util/vpd/lib/lib_vpd_test.c<br>A util/vpd/lib/math.c<br>A util/vpd/lib/vpd_container.c<br>A util/vpd/lib/vpd_decode.c<br>A util/vpd/lib/vpd_encode.c<br>A util/vpd/vpd.c<br>19 files changed, 3,886 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/15/25615/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/util/vpd/LICENSE b/util/vpd/LICENSE</span><br><span>new file mode 100644</span><br><span>index 0000000..d251496</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/LICENSE</span><br><span>@@ -0,0 +1,27 @@</span><br><span style="color: hsl(120, 100%, 40%);">+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+// Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+// modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+// met:</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+//    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+// notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+//    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+// copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+// in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+// distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+//    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+// contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+// this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+//</span><br><span style="color: hsl(120, 100%, 40%);">+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span><br><span style="color: hsl(120, 100%, 40%);">+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span><br><span style="color: hsl(120, 100%, 40%);">+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span><br><span style="color: hsl(120, 100%, 40%);">+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span><br><span style="color: hsl(120, 100%, 40%);">+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span><br><span>diff --git a/util/vpd/Makefile b/util/vpd/Makefile</span><br><span>new file mode 100644</span><br><span>index 0000000..0a42399</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/Makefile</span><br><span>@@ -0,0 +1,65 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+# Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+# found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+# modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+# met:</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+# notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+#    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+# copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+# in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+# distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+#    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+# contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+# this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span><br><span style="color: hsl(120, 100%, 40%);">+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span><br><span style="color: hsl(120, 100%, 40%);">+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span><br><span style="color: hsl(120, 100%, 40%);">+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span><br><span style="color: hsl(120, 100%, 40%);">+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Alternatively, this software may be distributed under the terms of the</span><br><span style="color: hsl(120, 100%, 40%);">+# GNU General Public License ("GPL") version 2 as published by the Free</span><br><span style="color: hsl(120, 100%, 40%);">+# Software Foundation.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+CC?=cc</span><br><span style="color: hsl(120, 100%, 40%);">+VERSION := $(shell ./util/getversion.sh)</span><br><span style="color: hsl(120, 100%, 40%);">+CFLAGS+=-g -Iinclude/ -Iinclude/lib -Werror -Wall -D'VPD_VERSION="$(VERSION)"'</span><br><span style="color: hsl(120, 100%, 40%);">+LDFLAGS+=-luuid</span><br><span style="color: hsl(120, 100%, 40%);">+BINARY=vpd</span><br><span style="color: hsl(120, 100%, 40%);">+STATIC_BINARY=vpd_s</span><br><span style="color: hsl(120, 100%, 40%);">+BINS=$(BINARY) $(STATIC_BINARY)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LIB_OBJS= \</span><br><span style="color: hsl(120, 100%, 40%);">+     lib/flashrom.o \</span><br><span style="color: hsl(120, 100%, 40%);">+      lib/fmap.o \</span><br><span style="color: hsl(120, 100%, 40%);">+  lib/lib_smbios.o \</span><br><span style="color: hsl(120, 100%, 40%);">+    lib/vpd_container.o \</span><br><span style="color: hsl(120, 100%, 40%);">+ lib/vpd_decode.o \</span><br><span style="color: hsl(120, 100%, 40%);">+    lib/vpd_encode.o \</span><br><span style="color: hsl(120, 100%, 40%);">+    lib/math.o</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+OBJS = $(LIB_OBJS) vpd.o</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+all: $(BINS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+$(BINARY): $(OBJS)</span><br><span style="color: hsl(120, 100%, 40%);">+  $(CC) -o $@ $? $(LDFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+$(STATIC_BINARY): $(OBJS)</span><br><span style="color: hsl(120, 100%, 40%);">+        $(CC) -static -o $@ $? $(LDFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+clean:</span><br><span style="color: hsl(120, 100%, 40%);">+   rm -f $(OBJS) $(BINS)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+.PHONY: clean test all</span><br><span>diff --git a/util/vpd/README.md b/util/vpd/README.md</span><br><span>new file mode 100644</span><br><span>index 0000000..b105016</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/README.md</span><br><span>@@ -0,0 +1,213 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# ChromeOS Vital Product Data (VPD) Binary Blob 2.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[TOC]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## Overview</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The [Chrome OS Platform VPD Reporting Specification](https://docs.google.com/a/google.com/document/d/1d2l5obmBYxgaJQvltEJD-oiLTb0M-RXG-pujG5VDa_A/edit?hl=en#)</span><br><span style="color: hsl(120, 100%, 40%);">+describes how a firmware image complies with the Chrome OS SMBIOS requirement.</span><br><span style="color: hsl(120, 100%, 40%);">+That document defines the required fields of type 0/1/127 tables and type 241</span><br><span style="color: hsl(120, 100%, 40%);">+binary blob pointers. However, the format of type 241 is left for each ODM to</span><br><span style="color: hsl(120, 100%, 40%);">+define. In most cases this is acceptable because Google is not involved in</span><br><span style="color: hsl(120, 100%, 40%);">+manufacturing and RMA processes.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The type 241 data often consists of component IDs and other items that affect</span><br><span style="color: hsl(120, 100%, 40%);">+the OEM software setup. Component IDs include network device IDs, IDs for</span><br><span style="color: hsl(120, 100%, 40%);">+removable devices (storage, RAM, etc), and other arbitrary ID types. OEM</span><br><span style="color: hsl(120, 100%, 40%);">+software information includes the default country code, language code, and so</span><br><span style="color: hsl(120, 100%, 40%);">+on.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Occasionally, modifying the vendor product data is required. Each OEM uses a</span><br><span style="color: hsl(120, 100%, 40%);">+proprietary format, which varies from model to model. To minimize variations,</span><br><span style="color: hsl(120, 100%, 40%);">+Google defined a standard format for the Vital Product Database (VPD) that is</span><br><span style="color: hsl(120, 100%, 40%);">+common, simple, and extensible.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This document describes the standard format for the VPD on Chrome devices. The</span><br><span style="color: hsl(120, 100%, 40%);">+format provides:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* An universal vendor product data format for all ODMs and OEMs</span><br><span style="color: hsl(120, 100%, 40%);">+* A method for tracking serial numbers for all removable or replaceable</span><br><span style="color: hsl(120, 100%, 40%);">+  components on a machine</span><br><span style="color: hsl(120, 100%, 40%);">+* A more efficient, usable approach for both manufacturing and Return Materials</span><br><span style="color: hsl(120, 100%, 40%);">+  Authorization (RMA) processes</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The format design principles were:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* Simple encoding implementation (no XML)</span><br><span style="color: hsl(120, 100%, 40%);">+* Flexible enough for different hardware configurations</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## **Syntax**</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The basic syntax for database entries is `{type, key, value} * n`. Instead of</span><br><span style="color: hsl(120, 100%, 40%);">+using a null-terminated ASCII string for key and value, we prefix a length for</span><br><span style="color: hsl(120, 100%, 40%);">+binary-safe. The string size varies according to the length value that precedes</span><br><span style="color: hsl(120, 100%, 40%);">+it. Every byte is contiguous and back-to-back. Padding the value is field</span><br><span style="color: hsl(120, 100%, 40%);">+allowed. To avoid parsing the VPD structure, the hardcoded fixed address can be</span><br><span style="color: hsl(120, 100%, 40%);">+used to read VPD values directly.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The following diagram illustrates the structure of the blob:</span><br><span style="color: hsl(120, 100%, 40%);">+![blob 2.0 diagram](_images/vpd_blob_2.0.png)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The entire binary blob is an array of `{key, value}` pairs. At the end, a `0x00`</span><br><span style="color: hsl(120, 100%, 40%);">+(`VPD_TYPE_TERMINATOR`) or a `0xFF` (`VPD_TYPE_IMPLICIT_TERMINATOR`) indicates</span><br><span style="color: hsl(120, 100%, 40%);">+the end of the array and the binary blob.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The combination of key and value can exceed 127 bytes. Setting the More bit to 1</span><br><span style="color: hsl(120, 100%, 40%);">+indicates the next byte has lower significant 7 bits in length.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## **Encoding example**</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The following example shows how to encode strings of normal length:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    <01> <04> "UUID"          <10> "0123456789ABCDEF"</span><br><span style="color: hsl(120, 100%, 40%);">+    <01> <07> "3G_IMEI"       <0E> "AABBBBBB-CC-DD"</span><br><span style="color: hsl(120, 100%, 40%);">+    <01> <0C> "ethernet_mac"  <06> <2A><02><03><B3><D5><7C></span><br><span style="color: hsl(120, 100%, 40%);">+    <00>   // the terminator</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The following example shows how to encode longer strings, like "any=Very long</span><br><span style="color: hsl(120, 100%, 40%);">+long long...":</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    <01> <03> "any"     <84><82><01> "Very long long long"...(65793 bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+    <00></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The VPD supports 4 types:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+| Type | Name                           | Description                        |</span><br><span style="color: hsl(120, 100%, 40%);">+|------|--------------------------------|------------------------------------|</span><br><span style="color: hsl(120, 100%, 40%);">+| 0x00 | `VPD_TYPE_TERMINATOR`          | Terminates VPD data.               |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0x01 | `VPD_TYPE_STRING`              | Encoded string length-value pair.  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0xFE | `VPD_TYPE_INFO`                | Key-value pair VPD info header.    |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0xFF | `VPD_TYPE_IMPLICIT_TERMINATOR` | Same as VPD_TYPE_TERMINATOR.       |</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Additional information:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+`VPD_TYPE_STRING` is made up of a key pair and a value pair.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+`VPD_TYPE_INFO` is a key-value pair the AP Firmware (sometimes referred as BIOS)</span><br><span style="color: hsl(120, 100%, 40%);">+uses to parse the VPD. The search pattern is,"`gVpdInfo`",(see `VPD_INFO_MAGIC`</span><br><span style="color: hsl(120, 100%, 40%);">+in the code) and the 4-byte size of VPD data follows.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+For details of each type, search for `VPD_TYPE_*` in the code.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## **Utility command examples**</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Chrome OS includes a utility for manipulating VPD data. The examples below show</span><br><span style="color: hsl(120, 100%, 40%);">+how to use the VPD utility to perform common tasks. Each task is described in</span><br><span style="color: hsl(120, 100%, 40%);">+the comment line preceding the example:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+```sh</span><br><span style="color: hsl(120, 100%, 40%);">+  # Dump all key-pairs in RO_VPD partition on the flash</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -l</span><br><span style="color: hsl(120, 100%, 40%);">+    "serial_number"="20100915SKU0015566"</span><br><span style="color: hsl(120, 100%, 40%);">+    "SKU"="SKU0001"</span><br><span style="color: hsl(120, 100%, 40%);">+    "UUID"="0001-0203_04050607"</span><br><span style="color: hsl(120, 100%, 40%);">+    "ethernet_mac"="2A:45:29_66:D4:57"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Dump RW_VPD partition</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -l -i "RW_VPD"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Rather using flashrom to access flash (usually slow), access a temp file.</span><br><span style="color: hsl(120, 100%, 40%);">+  % flashrom -r vpd.bin</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -f vpd.bin -l</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Add a new key-value pair, which value is a string (-s)</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -f vpd.bin -s "SKU"="0123456789ABCDEF"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Assign padding length in value field. -p must be in front of the -s</span><br><span style="color: hsl(120, 100%, 40%);">+  # you want to take effected on.</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -f vpd.bin -p 16 -s "SKU"="0123"</span><br><span style="color: hsl(120, 100%, 40%);">+  # In this case, the value of SKU is 16-byte long, which contains 12</span><br><span style="color: hsl(120, 100%, 40%);">+  # \0 at tail.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Add tons of key-value pairs at one time.</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -f vpd.bin -p 32 -s "serial_number"="20101214_MARIO_1122" \</span><br><span style="color: hsl(120, 100%, 40%);">+                   -p 16 -s "ethernet_mac"="11:22:33:44:55:66" \</span><br><span style="color: hsl(120, 100%, 40%);">+                         -s "mlb_serial_number"="2037291738734" \</span><br><span style="color: hsl(120, 100%, 40%);">+                   -p 8  -s "UUID"="2323-3524-2344364-133456" \</span><br><span style="color: hsl(120, 100%, 40%);">+                   ...</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # By default, utility accesses "RO_VPD" on flash. You can specify -i</span><br><span style="color: hsl(120, 100%, 40%);">+  # parameter to access particular partition.</span><br><span style="color: hsl(120, 100%, 40%);">+  # PS. -O means overwriting any garbage in partition.</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd -i "RW_VPD" -O -s "ActivateDate=2011/03/02 11:22:33"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Read a specific key-value pair. Specially useful in shell script.</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -g "mlb_serial_number"</span><br><span style="color: hsl(120, 100%, 40%);">+    MB20100914_012345</span><br><span style="color: hsl(120, 100%, 40%);">+  # no key string and no quotes in output.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Delete a key-value pair</span><br><span style="color: hsl(120, 100%, 40%);">+  % vpd -f vpd.bin -d "3G_IMEI"</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## Partition names</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The AP firmware image for Chrome OS has two VPD partitions. Each stores a</span><br><span style="color: hsl(120, 100%, 40%);">+specific type of data:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* `RO_VPD` partition in the read-only area. Stores machine-specific information,</span><br><span style="color: hsl(120, 100%, 40%);">+  like the mainboard serial number and MAC address.</span><br><span style="color: hsl(120, 100%, 40%);">+* `RW_VPD` partition in the writeable area. Stores all data that will be updated</span><br><span style="color: hsl(120, 100%, 40%);">+  after a device leaves the factory.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Note that the naming convention includes the underscore ( _ ) character.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## VPD fields</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Although VPD 2.0 doesn't define a fixed data structure, Google requires partners</span><br><span style="color: hsl(120, 100%, 40%);">+to include specific VPD fields in the AP firmware image, for example</span><br><span style="color: hsl(120, 100%, 40%);">+`serial_number`. The list of VPD fields are available in the ChromeOS Partner</span><br><span style="color: hsl(120, 100%, 40%);">+Site document "VPD Field Requirements".</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+In theory the VPD name can be arbitrary string, but in order to simplify</span><br><span style="color: hsl(120, 100%, 40%);">+processing, the utility only accepts names in CamelCase or lower_underline,</span><br><span style="color: hsl(120, 100%, 40%);">+i.e., in regular expression `[a-zA-Z0-9_]+`.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## Appendix A</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This information is intended for a developer audience.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+### Type enumerates used in 'type' field.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+| Value | Type                     |</span><br><span style="color: hsl(120, 100%, 40%);">+|-------|--------------------------|</span><br><span style="color: hsl(120, 100%, 40%);">+| 0x00  | The terminator           |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0x01  | String                   |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0xFE  | Info header              |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0xFF  | The implicit terminator. |</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+On the flash media, a non-programmed byte is 0xFF. When decoder reads this</span><br><span style="color: hsl(120, 100%, 40%);">+type, it should assume no more pairs are present after this byte.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+### Values in Binary Blob Pointer (Type 241)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+| Offset  | Name                    | Length   | Value                                |</span><br><span style="color: hsl(120, 100%, 40%);">+|---------|-------------------------|----------|--------------------------------------|</span><br><span style="color: hsl(120, 100%, 40%);">+| 00h     | Type                    | BYTE     | 241                                  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 01h     | Length                  | BYTE     | Varies                               |</span><br><span style="color: hsl(120, 100%, 40%);">+| 02h     | Handle                  | WORD     | Varies                               |</span><br><span style="color: hsl(120, 100%, 40%);">+| 04h     | Structure Major Version | BYTE     | 01h                                  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 05h     | Structure Minor Version | BYTE     | 00h                                  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 06h     | Blob Vendor             | BYTE     | 1 "Google"                           |</span><br><span style="color: hsl(120, 100%, 40%);">+| 07h     | Blob Description        | BYTE     | 2 "VPD 2.0"                          |</span><br><span style="color: hsl(120, 100%, 40%);">+| 08h     | Blob Major Version      | BYTE     | 2                                    |</span><br><span style="color: hsl(120, 100%, 40%);">+| 09h     | Blob Minor Version      | BYTE     | 0                                    |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0Ah     | Blob Variant            | BYTE     | 3 ""                                 |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0Bh-0Fh | Reserved                |          |                                      |</span><br><span style="color: hsl(120, 100%, 40%);">+| 10h-1Fh | Blob UUID               | 16 BYTES | 0a7c23d3-8a27-4252-99bf-7868a2e26b61 |</span><br><span style="color: hsl(120, 100%, 40%);">+| 20h-23h | Offset                  | DWORD    | Varies                               |</span><br><span style="color: hsl(120, 100%, 40%);">+| 24h-27h | Size                    | DWORD    | Varies                               |</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+## Change Log</span><br><span style="color: hsl(120, 100%, 40%);">+| Version | Date       | Changes                                               |</span><br><span style="color: hsl(120, 100%, 40%);">+|---------|------------|-------------------------------------------------------|</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.17    | 2014/02/27 | Added VPD_TYPE_INFO                                   |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.12    | 2011/04/20 | Reorganized content, updated available options        |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.7     | 2011/03/11 | Added VPD partition names and required field          |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.6     | 2011/03/08 | Made small refinement to Binary Blob Pointer values   |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.5     | 2011/03/02 | Added RW VPD example                                  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.4     | 2010/12/13 | Fixed the command style                               |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.3     | 2010/12/14 | Added the implicit terminator (0xFF)                  |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.2     | 2010/12/08 | Added type field. Allowed padding.                    |</span><br><span style="color: hsl(120, 100%, 40%);">+| 0.1     | 2010/09/14 | Draft version.                                        |</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/util/vpd/include/lib/flashrom.h b/util/vpd/include/lib/flashrom.h</span><br><span>new file mode 100644</span><br><span>index 0000000..0849b6d</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/flashrom.h</span><br><span>@@ -0,0 +1,45 @@</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+ * modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+ * met:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ * notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+ * copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+ * distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+ * contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+ * this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_FLASHROM_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_FLASHROM_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  FLASHROM_OK = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  FLASHROM_FAIL,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromFullRead(const char* full_file);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromPartialRead(const char* part_file, const char* full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const char* partition_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromPartialWrite(const char* part_file, const char* full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                         const char* partition_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __LIB_FLASHROM_H__ */</span><br><span>diff --git a/util/vpd/include/lib/fmap.h b/util/vpd/include/lib/fmap.h</span><br><span>new file mode 100644</span><br><span>index 0000000..148ecc2</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/fmap.h</span><br><span>@@ -0,0 +1,129 @@</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+ * modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+ * met:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ * notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+ * copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+ * distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+ * contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+ * this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span><br><span style="color: hsl(120, 100%, 40%);">+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span><br><span style="color: hsl(120, 100%, 40%);">+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span><br><span style="color: hsl(120, 100%, 40%);">+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Alternatively, this software may be distributed under the terms of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License ("GPL") version 2 as published by the Free</span><br><span style="color: hsl(120, 100%, 40%);">+ * Software Foundation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The fmap document can be found in</span><br><span style="color: hsl(120, 100%, 40%);">+ *     http://code.google.com/p/flashmap/wiki/FmapSpec.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_FMAP_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_FMAP_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define FMAP_SIGNATURE    "__FMAP__"</span><br><span style="color: hsl(120, 100%, 40%);">+#define FMAP_VER_MAJOR    1  /* this header's FMAP minor version */</span><br><span style="color: hsl(120, 100%, 40%);">+#define FMAP_VER_MINOR    0  /* this header's FMAP minor version */</span><br><span style="color: hsl(120, 100%, 40%);">+#define FMAP_STRLEN    32    /* maximum length for strings, */</span><br><span style="color: hsl(120, 100%, 40%);">+                             /* including null-terminator */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  FMAP_OK = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  FMAP_FAIL,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum fmap_flags {</span><br><span style="color: hsl(120, 100%, 40%);">+  FMAP_AREA_STATIC  = 1 << 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  FMAP_AREA_COMPRESSED  = 1 << 1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct crypto_algo;  /* forward declaration */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Mapping of volatile and static regions in firmware binary */</span><br><span style="color: hsl(120, 100%, 40%);">+struct fmap {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t signature[8];    /* "__FMAP__" (0x5F5F50414D465F5F) */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t ver_major;    /* major version */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t ver_minor;    /* minor version */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t base;      /* address of the firmware binary */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t size;      /* size of firmware binary in bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+  char name[FMAP_STRLEN];  /* name of this firmware binary */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t nareas;    /* number of areas described by</span><br><span style="color: hsl(120, 100%, 40%);">+             fmap_areas[] below */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct fmap_area {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t offset;    /* offset relative to base */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t size;      /* size in bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+    char name[FMAP_STRLEN];  /* descriptive name */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t flags;      /* flags for this area */</span><br><span style="color: hsl(120, 100%, 40%);">+  }  __attribute__((packed)) areas[];</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * fmapNormalizeAreaName - to protect malicious attack, this function</span><br><span style="color: hsl(120, 100%, 40%);">+ * replace not allowed chars into underline. Only following are allowed:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   numbers</span><br><span style="color: hsl(120, 100%, 40%);">+ *   digits</span><br><span style="color: hsl(120, 100%, 40%);">+ *   space</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The allowing list should increase if fmap area name allows more chars.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @name: point to the name.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void fmapNormalizeAreaName(char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * fmapFind - finds FMAP signature in a binary image</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @image:  binary image</span><br><span style="color: hsl(120, 100%, 40%);">+ * @len:  length of binary image</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function does no error checking. The caller is responsible for</span><br><span style="color: hsl(120, 100%, 40%);">+ * verifying that the contents are sane.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns offset of FMAP signature to indicate success</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns <0 to indicate failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+off_t fmapFind(const uint8_t *image, size_t image_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * fmapGetArea - finds the area in a binary image</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @name: name to search</span><br><span style="color: hsl(120, 100%, 40%);">+ * @image: points to the start of image</span><br><span style="color: hsl(120, 100%, 40%);">+ * @image_len: length of the image</span><br><span style="color: hsl(120, 100%, 40%);">+ * @offset: pointer to store the offset of the found area</span><br><span style="color: hsl(120, 100%, 40%);">+ * @size: pointer to store the size of the found area.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function returns FMAP_OK if found. Returns FMAP_FAIL if not found.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int fmapGetArea(const char *name, const struct fmap *fmap,</span><br><span style="color: hsl(120, 100%, 40%);">+                uint32_t *offset, uint32_t *size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif  /* __LIB_FMAP_H__*/</span><br><span>diff --git a/util/vpd/include/lib/lib_smbios.h b/util/vpd/include/lib/lib_smbios.h</span><br><span>new file mode 100644</span><br><span>index 0000000..1e1cef8</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/lib_smbios.h</span><br><span>@@ -0,0 +1,34 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_LIB_SMBIOS__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_LIB_SMBIOS__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/vpd_tables.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_entry *vpd_create_eps(unsigned short structure_table_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 unsigned short num_structures,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 uint32_t eps_base);</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_append_type241(uint16_t handle, uint8_t **buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                       size_t len, const char *uuid, uint32_t offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                       uint32_t size, const char *vendor,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const char *desc, const char *variant);</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_type241_size(struct vpd_header *header);</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_append_type127(uint16_t handle,</span><br><span style="color: hsl(120, 100%, 40%);">+                       uint8_t **buf, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif  /* __LIB_LIB_SMBIOS__ */</span><br><span>diff --git a/util/vpd/include/lib/lib_vpd.h b/util/vpd/include/lib/lib_vpd.h</span><br><span>new file mode 100644</span><br><span>index 0000000..d40c9a8</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/lib_vpd.h</span><br><span>@@ -0,0 +1,261 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2013 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_VPD__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_VPD__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum vpd_err {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* These error codes are returned to the shell as exit codes. If they are</span><br><span style="color: hsl(120, 100%, 40%);">+    * changed then callers such as Enterprise.VpdCheck from histograms.xml must</span><br><span style="color: hsl(120, 100%, 40%);">+    * be updated along with tests/functions.sh. If codes are added then they</span><br><span style="color: hsl(120, 100%, 40%);">+    * must not conflict with conventional exit codes:</span><br><span style="color: hsl(120, 100%, 40%);">+    * http://www.tldp.org/LDP/abs/html/exitcodes.html</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_OK              = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_FAIL            = 3,   /* generic vpd utility error */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_SYSTEM      = 4,   /* system error (file error, out of memory, etc) */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_ROM_READ    = 5,   /* error reading ROM (e.g. thru flashrom) */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_ROM_WRITE   = 6,   /* error writing ROM (e.g. thru flashrom) */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_SYNTAX      = 7,   /* command syntax error */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_PARAM       = 8,   /* invalid parameter specified by user */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_NOT_FOUND   = 9,   /* VPD not found */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_OVERFLOW    = 10,  /* boundary exceeded */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_ERR_INVALID     = 11,  /* error in VPD - possible corruption or bug */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef enum vpd_err vpd_err_t;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_TERMINATOR = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_INFO                = 0xfe,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_IMPLICIT_TERMINATOR = 0xff,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_AS_LONG_AS = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {  /* export_type */</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_EXPORT_KEY_VALUE = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_EXPORT_VALUE,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_EXPORT_AS_PARAMETER,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_EXPORT_NULL_TERMINATE,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Callback for decodeVpdString to invoke. */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef vpd_err_t VpdDecodeCallback(const uint8_t *key, int32_t key_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    const uint8_t *value, int32_t value_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    void *arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Container data types */</span><br><span style="color: hsl(120, 100%, 40%);">+struct StringPair {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *key;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *value;</span><br><span style="color: hsl(120, 100%, 40%);">+  int pad_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int filter_out;  /* TRUE means not exported. */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *next;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct PairContainer {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *first;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Encode and decode VPD entries</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Encodes the len into multiple bytes with the following format.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    7   6 ............ 0</span><br><span style="color: hsl(120, 100%, 40%);">+ *  +----+------------------+</span><br><span style="color: hsl(120, 100%, 40%);">+ *  |More|      Length      |  ...</span><br><span style="color: hsl(120, 100%, 40%);">+ *  +----+------------------+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The encode_buf points to the actual position we are going to store.</span><br><span style="color: hsl(120, 100%, 40%);">+ * encoded_len will return the exact bytes we encoded in this function.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns fail if the buffer is not long enough.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeLen(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *encode_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *encoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Given an encoded string, this functions decodes the length field which varies</span><br><span style="color: hsl(120, 100%, 40%);">+ * from 1 byte to many bytes.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The in points the actual byte going to be decoded. The *length returns</span><br><span style="color: hsl(120, 100%, 40%);">+ * the decoded length field. The number of consumed bytes will be stroed in</span><br><span style="color: hsl(120, 100%, 40%);">+ * decoded_len.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns VPD_FAIL if more bit is 1, but actually reaches the end of string.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeLen(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *in,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *length,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *decoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Encodes the terminator.</span><br><span style="color: hsl(120, 100%, 40%);">+ * When calling, the output_buf should point to the start of buffer while</span><br><span style="color: hsl(120, 100%, 40%);">+ * *generated_len should contain how many bytes exist in buffer now.</span><br><span style="color: hsl(120, 100%, 40%);">+ * After return, *generated_len would be plused the number of bytes generated</span><br><span style="color: hsl(120, 100%, 40%);">+ * in this function.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeVpdTerminator(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int max_buffer_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int *generated_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Encodes the given type/key/value pair into buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The pad_value_len is used to control the output value length.</span><br><span style="color: hsl(120, 100%, 40%);">+ * When pad_value_len > 0, the value is outputted into fixed length (pad \0</span><br><span style="color: hsl(120, 100%, 40%);">+ *                         if the value is shorter). Truncated if too long.</span><br><span style="color: hsl(120, 100%, 40%);">+ *      pad_value_len == VPD_NO_LIMIT, output the value as long as possible.</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is useful when we want to fix the structure layout at beginning.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The encoded string will be stored in output_buf. If it is longer than</span><br><span style="color: hsl(120, 100%, 40%);">+ * max_buffer_len, this function returns fail. If the buffer is long enough,</span><br><span style="color: hsl(120, 100%, 40%);">+ * the generated_len will be updated.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * When calling, the output_buf should point to the start of buffer while</span><br><span style="color: hsl(120, 100%, 40%);">+ * *generated_len should contain how many bytes exist in buffer now.</span><br><span style="color: hsl(120, 100%, 40%);">+ * After return, *generated_len would be plused the number of bytes generated</span><br><span style="color: hsl(120, 100%, 40%);">+ * in this function.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The initial value of *generated_len can be non-zero, so that this value</span><br><span style="color: hsl(120, 100%, 40%);">+ * can be used between multiple calls to encodeVpd2Pair().</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeVpdString(</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int pad_value_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int max_buffer_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int *generated_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Given the encoded string, this function invokes callback with extracted</span><br><span style="color: hsl(120, 100%, 40%);">+ * (key, value). The *consumed will be plused the number of bytes consumed in</span><br><span style="color: hsl(120, 100%, 40%);">+ * this function.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The input_buf points to the first byte of the input buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The *consumed starts from 0, which is actually the next byte to be decoded.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It can be non-zero to be used in multiple calls.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If one entry is successfully decoded, sends it to callback and returns the</span><br><span style="color: hsl(120, 100%, 40%);">+ * result.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeVpdString(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *input_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *consumed,</span><br><span style="color: hsl(120, 100%, 40%);">+    VpdDecodeCallback callback,</span><br><span style="color: hsl(120, 100%, 40%);">+    void *callback_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Container helpers</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+void initContainer(struct PairContainer *container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct StringPair *findString(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                              const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct StringPair ***prev_next);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* If key is already existed in container, its value will be replaced.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If not existed, creates new entry in container.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void setString(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+               const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+               const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+               const int pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* merge all entries in src into dst. If key is duplicate, overwrite it.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void mergeContainer(struct PairContainer *dst,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct PairContainer *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* subtract src from dst.</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+int subtractContainer(struct PairContainer *dst,</span><br><span style="color: hsl(120, 100%, 40%);">+                      const struct PairContainer *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Given a container, encode its all entries into the buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeContainer(const struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          int *generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Given a VPD blob, decode its entries and push into container.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeToContainer(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const uint8_t *input_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                            int32_t *consumed);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Set filter for exporting functions.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If filter is NULL, resets the filter so that everything can be exported.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t setContainerFilter(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                             const uint8_t *filter);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Remove a key.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns VPD_OK if deleted successfully. Otherwise, VPD_FAIL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t deleteKey(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const uint8_t *key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns number of pairs in container.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int lenOfContainer(const struct PairContainer *container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Export the value in raw format.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The buf points to the first byte of buffer and *generated contains the number</span><br><span style="color: hsl(120, 100%, 40%);">+ * of bytes already existed in buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Afterward, the *generated will be plused on exact bytes this function has</span><br><span style="color: hsl(120, 100%, 40%);">+ * generated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t exportStringValue(const struct StringPair *str,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                            uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                            int *generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Export the container content with human-readable text.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The buf points to the first byte of buffer and *generated contains the number</span><br><span style="color: hsl(120, 100%, 40%);">+ * of bytes already existed in buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Afterward, the *generated will be plused on exact bytes this function has</span><br><span style="color: hsl(120, 100%, 40%);">+ * generated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t exportContainer(const int export_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          int *generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void destroyContainer(struct PairContainer *container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif  /* __LIB_VPD__ */</span><br><span>diff --git a/util/vpd/include/lib/math.h b/util/vpd/include/lib/math.h</span><br><span>new file mode 100644</span><br><span>index 0000000..5fd50c8</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/math.h</span><br><span>@@ -0,0 +1,80 @@</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_MATH_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_MATH_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Count the number of low-order 0 bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+extern int ctz(unsigned long long int u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Get the integral log2 of a number.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If n is not a perfect power of 2, this function will return return the</span><br><span style="color: hsl(120, 100%, 40%);">+ * log2 of the largest power of 2 less than n.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If n is negative, this functions will return the log of abs(n).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+extern int logbase2(int n);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * rolling8_csum  -  Bytewise rolling summation "checksum" of a buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @buf:  buffer to sum</span><br><span style="color: hsl(120, 100%, 40%);">+ * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+extern uint8_t rolling8_csum(uint8_t *buf, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+  * zero8_csum - Calculates 8-bit zero-sum checksum</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * @buf:  input buffer</span><br><span style="color: hsl(120, 100%, 40%);">+  * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * The summation of the bytes in the array and the csum will equal zero</span><br><span style="color: hsl(120, 100%, 40%);">+  * for 8-bit data size.</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * returns checksum to indicate success</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+extern uint8_t zero8_csum(uint8_t *buf, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __mask</span><br><span style="color: hsl(120, 100%, 40%);">+# define __mask(high, low) ((1ULL << (high)) + \</span><br><span style="color: hsl(120, 100%, 40%);">+                            (((1ULL << (high)) - 1) - ((1ULL << (low)) - 1)))</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __min</span><br><span style="color: hsl(120, 100%, 40%);">+# define __min(a, b)  ((a) < (b) ? (a) : (b))</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __max</span><br><span style="color: hsl(120, 100%, 40%);">+# define __max(a, b)  ((a) > (b) ? (a) : (b))</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __abs</span><br><span style="color: hsl(120, 100%, 40%);">+# define __abs(x) (x < 0 ? -x : x)</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __LIB_MATH_H__ */</span><br><span>diff --git a/util/vpd/include/lib/vpd.h b/util/vpd/include/lib/vpd.h</span><br><span>new file mode 100644</span><br><span>index 0000000..be59660</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/vpd.h</span><br><span>@@ -0,0 +1,53 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_VPD_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_VPD_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* VPD Table Types */</span><br><span style="color: hsl(120, 100%, 40%);">+enum vpd_types {</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_FIRMWARE = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_SYSTEM,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_END                  = 127,</span><br><span style="color: hsl(120, 100%, 40%);">+  VPD_TYPE_BINARY_BLOB_POINTER  = 241,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_SPD_OFFSET 0x400</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_SPD_UUID "75f4926b-9e43-4b32-8979-eb20c0eda76a"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_SPD_VENDOR "Google"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_SPD_DESCRIPTION "Google SPD"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_SPD_VARIANT ""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_2_0_OFFSET 0x600</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_2_0_UUID "0a7c23d3-8a27-4252-99bf-7868a2e26b61"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_2_0_VENDOR "Google"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_2_0_DESCRIPTION "Google VPD 2.0"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_2_0_VARIANT ""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_1_2_OFFSET 0x100</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_1_2_UUID "08f8a2b0-15fd-4cfd-968f-8378f2c508ce"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_1_2_VENDOR "Google"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_1_2_DESCRIPTION "Google VPD 1.2"</span><br><span style="color: hsl(120, 100%, 40%);">+#define GOOGLE_VPD_1_2_VARIANT ""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_EPS_VPD_MAJOR_VERSION 2</span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_EPS_VPD_MINOR_VERSION 6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __LIB_VPD_H__ */</span><br><span>diff --git a/util/vpd/include/lib/vpd_tables.h b/util/vpd/include/lib/vpd_tables.h</span><br><span>new file mode 100644</span><br><span>index 0000000..f1060af</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/include/lib/vpd_tables.h</span><br><span>@@ -0,0 +1,117 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2014 Google Inc.  All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __LIB_VPD_TABLES_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __LIB_VPD_TABLES_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define VPD_ENTRY_MAGIC    "_SM_"</span><br><span style="color: hsl(120, 100%, 40%);">+#define VPD_INFO_MAGIC     \</span><br><span style="color: hsl(120, 100%, 40%);">+  "\xfe"      /* type: VPD header */       \</span><br><span style="color: hsl(120, 100%, 40%);">+  "\x09"      /* key length, 9 = 1 + 8 */  \</span><br><span style="color: hsl(120, 100%, 40%);">+  "\x01"      /* info version, 1 */        \</span><br><span style="color: hsl(120, 100%, 40%);">+  "gVpdInfo"  /* signature, 8 bytes */ \</span><br><span style="color: hsl(120, 100%, 40%);">+  "\x04"      /* value length */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Google specific VPD info */</span><br><span style="color: hsl(120, 100%, 40%);">+struct google_vpd_info {</span><br><span style="color: hsl(120, 100%, 40%);">+  union {</span><br><span style="color: hsl(120, 100%, 40%);">+    struct {</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t type;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t key_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t info_ver;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t signature[8];</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+    } tlv;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t magic[12];</span><br><span style="color: hsl(120, 100%, 40%);">+  } header;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Entry */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_entry {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t anchor_string[4];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t entry_cksum;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t entry_length;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t major_ver;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t minor_ver;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t max_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t entry_rev;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t format_area[5];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t inter_anchor_string[5];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t inter_anchor_cksum;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t table_length;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t table_address;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t table_entry_count;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t bcd_revision;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Header */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_header {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t type;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t length;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t handle;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Type 0 - firmware information */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_table_firmware {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t vendor;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint16_t start_address;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t release_date;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t rom_size_64k_blocks;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t characteristics;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t extension[2];  /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t major_ver;     /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t minor_ver;     /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t ec_major_ver;  /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t ec_minor_ver;  /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Type 1 - system information */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_table_system {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t manufacturer;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t name;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t serial_number;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t uuid[16];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t wakeup_type;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t sku_number;  /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t family;      /* v2.4+ */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Type 127 - end of table */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_table_eot {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_header header;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Type 241 - binary blob pointer */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_table_binary_blob_pointer {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t struct_major_version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t struct_minor_version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t vendor;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t description;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t major_version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t minor_version;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t variant;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t reserved[5];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t uuid[16];</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The length and number of strings defined here is not a limitation of VPD.</span><br><span style="color: hsl(120, 100%, 40%);">+ * These numbers were deemed good enough during development. */</span><br><span style="color: hsl(120, 100%, 40%);">+#define VPD_MAX_STRINGS 10</span><br><span style="color: hsl(120, 100%, 40%);">+#define VPD_MAX_STRING_LENGTH 64</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __LIB_VPD_TABLES_H__ */</span><br><span>diff --git a/util/vpd/lib/flashrom.c b/util/vpd/lib/flashrom.c</span><br><span>new file mode 100644</span><br><span>index 0000000..67d346c</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/flashrom.c</span><br><span>@@ -0,0 +1,90 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2010, Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+ * modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+ * met:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ * notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+ * copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+ * distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+ * contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+ * this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/flashrom.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The best choice is PATH_MAX. However, it leads portibility issue.</span><br><span style="color: hsl(120, 100%, 40%);">+ * So, define a long enough length here. */</span><br><span style="color: hsl(120, 100%, 40%);">+#define CMD_BUF_SIZE (4096)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t flashrom_cmd[] = "flashrom";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The argument for flashrom.</span><br><span style="color: hsl(120, 100%, 40%);">+ *   bus=spi: The VPD data are stored in BIOS flash, which is attached</span><br><span style="color: hsl(120, 100%, 40%);">+ *            to the SPI bus.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t flashrom_arguments[] = " -p host ";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromFullRead(const char* full_file) {</span><br><span style="color: hsl(120, 100%, 40%);">+  char cmd[CMD_BUF_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+  int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  snprintf(cmd, sizeof(cmd), "%s %s -r '%s' >/dev/null 2>&1",</span><br><span style="color: hsl(120, 100%, 40%);">+           flashrom_cmd, flashrom_arguments, full_file);</span><br><span style="color: hsl(120, 100%, 40%);">+  ret = system(cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ret == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromPartialRead(const char* part_file, const char* full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const char* partition_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+  char cmd[CMD_BUF_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+  int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  snprintf(cmd, sizeof(cmd), "%s %s -i FMAP -i '%s':'%s' "</span><br><span style="color: hsl(120, 100%, 40%);">+                             "-r '%s' >/dev/null 2>&1",</span><br><span style="color: hsl(120, 100%, 40%);">+           flashrom_cmd, flashrom_arguments,</span><br><span style="color: hsl(120, 100%, 40%);">+           partition_name, part_file, full_file);</span><br><span style="color: hsl(120, 100%, 40%);">+  ret = system(cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ret == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int flashromPartialWrite(const char* part_file, const char* full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                         const char* partition_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+  char cmd[CMD_BUF_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+  int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* write it back */</span><br><span style="color: hsl(120, 100%, 40%);">+  snprintf(cmd, sizeof(cmd),</span><br><span style="color: hsl(120, 100%, 40%);">+           "%s %s -i '%s':'%s' -w '%s' --fast-verify >/dev/null 2>&1",</span><br><span style="color: hsl(120, 100%, 40%);">+           flashrom_cmd, flashrom_arguments,</span><br><span style="color: hsl(120, 100%, 40%);">+           partition_name, part_file, full_file);</span><br><span style="color: hsl(120, 100%, 40%);">+  ret = system(cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ret == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+    return FLASHROM_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/fmap.c b/util/vpd/lib/fmap.c</span><br><span>new file mode 100644</span><br><span>index 0000000..bb6919c</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/fmap.c</span><br><span>@@ -0,0 +1,109 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright 2010, Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Redistribution and use in source and binary forms, with or without</span><br><span style="color: hsl(120, 100%, 40%);">+ * modification, are permitted provided that the following conditions are</span><br><span style="color: hsl(120, 100%, 40%);">+ * met:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions of source code must retain the above copyright</span><br><span style="color: hsl(120, 100%, 40%);">+ * notice, this list of conditions and the following disclaimer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Redistributions in binary form must reproduce the above</span><br><span style="color: hsl(120, 100%, 40%);">+ * copyright notice, this list of conditions and the following disclaimer</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the documentation and/or other materials provided with the</span><br><span style="color: hsl(120, 100%, 40%);">+ * distribution.</span><br><span style="color: hsl(120, 100%, 40%);">+ *    * Neither the name of Google Inc. nor the names of its</span><br><span style="color: hsl(120, 100%, 40%);">+ * contributors may be used to endorse or promote products derived from</span><br><span style="color: hsl(120, 100%, 40%);">+ * this software without specific prior written permission.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span><br><span style="color: hsl(120, 100%, 40%);">+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span><br><span style="color: hsl(120, 100%, 40%);">+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span><br><span style="color: hsl(120, 100%, 40%);">+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span><br><span style="color: hsl(120, 100%, 40%);">+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span><br><span style="color: hsl(120, 100%, 40%);">+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span><br><span style="color: hsl(120, 100%, 40%);">+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span><br><span style="color: hsl(120, 100%, 40%);">+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Alternatively, this software may be distributed under the terms of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License ("GPL") version 2 as published by the Free</span><br><span style="color: hsl(120, 100%, 40%);">+ * Software Foundation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The fmap document can be found in</span><br><span style="color: hsl(120, 100%, 40%);">+ *     https://github.com/dhendrix/flashmap/blob/wiki/FmapSpec.md</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ctype.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/fmap.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fmapNormalizeAreaName(char *name) {</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  while (*name) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(isascii(*name) && isalnum(*name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      *name = '_';</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    name++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+off_t fmapFind(const uint8_t *image, size_t image_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  off_t offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t sig;</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct fmap *header;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(sig) == strlen(FMAP_SIGNATURE));</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(&sig, FMAP_SIGNATURE, strlen(FMAP_SIGNATURE));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Find 4-byte aligned FMAP signature within image.</span><br><span style="color: hsl(120, 100%, 40%);">+   * According to fmap document, http://code.google.com/p/flashmap/wiki/FmapSpec</span><br><span style="color: hsl(120, 100%, 40%);">+   * fmap 1.01 changes to use 64-byte alignment, but 1.00 used 4-byte.</span><br><span style="color: hsl(120, 100%, 40%);">+   * For backward-compatible, uses 4-byte alignment to search.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (offset = 0; offset + sizeof(*header) <= image_len; offset += 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (0 != memcmp(&image[offset], &sig, sizeof(sig))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    header = (const struct fmap *)(&image[offset]);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (header->ver_major != FMAP_VER_MAJOR) {</span><br><span style="color: hsl(120, 100%, 40%);">+      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    return offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ *  TODO: need more sanity check for fmap.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int fmapGetArea(const char *name, const struct fmap *fmap,</span><br><span style="color: hsl(120, 100%, 40%);">+                uint32_t *offset, uint32_t *size) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(offset);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* traverse whole table */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < fmap->nareas; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (0 == strcmp(fmap->areas[i].name, name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      *offset = fmap->areas[i].offset;</span><br><span style="color: hsl(120, 100%, 40%);">+      *size = fmap->areas[i].size;</span><br><span style="color: hsl(120, 100%, 40%);">+      return FMAP_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return FMAP_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/lib_smbios.c b/util/vpd/lib/lib_smbios.c</span><br><span>new file mode 100644</span><br><span>index 0000000..f27a647</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/lib_smbios.c</span><br><span>@@ -0,0 +1,288 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2010 Google Inc.  All Rights Reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Ported from mosys project (http://code.google.com/p/mosys/)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ctype.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <uuid/uuid.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/math.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_smbios.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/vpd_tables.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function simply looks for the pattern of two adjacent NULL bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ * following the table header.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_sizeof_strings(void *table)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *p;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_header *header = table;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t size = 0, offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char cmp[2] = { '\0', '\0' };</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t found = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+   * Search for double NULL. End of strings will be one byte before the</span><br><span style="color: hsl(120, 100%, 40%);">+   * final terminator which indicates end of structure.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (p = table + header->length - 1; p; p++, offset++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!memcmp(p, cmp, 2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      found = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      break;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (found)</span><br><span style="color: hsl(120, 100%, 40%);">+    size = offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * vpd_crete_eps - create an entry point structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @structure_table_len:  structure table len</span><br><span style="color: hsl(120, 100%, 40%);">+ * @num_structures:    number of structures in structure table</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * As per SMBIOS spec, the caller must place this structure on a 16-byte</span><br><span style="color: hsl(120, 100%, 40%);">+ * boundary so that the anchor strings can be found.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns pointer to newly allocated entry point structure if successful</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns NULL to indicate failure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * FIXME: This function needs to be more intelligent about parsing tables and</span><br><span style="color: hsl(120, 100%, 40%);">+ * obtaining information on its own. These arguments need to go away.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct vpd_entry *vpd_create_eps(uint16_t structure_table_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 uint16_t num_structures,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 uint32_t eps_base) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_entry *eps = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* size of structure only, no strings */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps = malloc(sizeof(struct vpd_entry));</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!eps)</span><br><span style="color: hsl(120, 100%, 40%);">+    return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(eps, 0, sizeof(*eps));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(eps->anchor_string, VPD_ENTRY_MAGIC, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Note: entry point length should be 0x1F for v2.6 */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->entry_length = sizeof(struct vpd_entry);</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->major_ver = CONFIG_EPS_VPD_MAJOR_VERSION;</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->minor_ver = CONFIG_EPS_VPD_MINOR_VERSION;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* EPS revision based on version 2.1 or later */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->entry_rev = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* note: nothing done with EPS formatted area */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Intermediate EPS (IEPS) stuff */</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(eps->inter_anchor_string, "_DMI_", 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME: implement vpd_table_length() and vpd_num_structures() */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->table_length = structure_table_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* immediately follow the entry point structure */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->table_address = eps_base + eps->entry_length;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef CONFIG_EPS_NUM_STRUCTURES</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->table_entry_count = CONFIG_EPS_NUM_STRUCTURES;</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->table_entry_count = num_structures;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->bcd_revision = (CONFIG_EPS_VPD_MAJOR_VERSION << 4) |</span><br><span style="color: hsl(120, 100%, 40%);">+                      CONFIG_EPS_VPD_MINOR_VERSION;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* calculate IEPS checksum first, then the EPS checksum */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->inter_anchor_cksum = zero8_csum(&eps->inter_anchor_string[0], 0xf);</span><br><span style="color: hsl(120, 100%, 40%);">+  eps->entry_cksum = zero8_csum((uint8_t *)eps, eps->entry_length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return eps;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * vpd_append_type127 - append type 127 (end of table) structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @handle:  handle for this structure</span><br><span style="color: hsl(120, 100%, 40%);">+ * @buf:  buffer to append to</span><br><span style="color: hsl(120, 100%, 40%);">+ * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns total size of newly re-sized buffer if successful</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns <0 to indicate failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_append_type127(uint16_t handle, uint8_t **buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_table_eot *data;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t total_len, struct_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  struct_len = sizeof(struct vpd_table_eot) + 2;  /* double terminator */</span><br><span style="color: hsl(120, 100%, 40%);">+  total_len = len + struct_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *buf = realloc(*buf, total_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  data = (struct vpd_table_eot *)(*buf + len);</span><br><span style="color: hsl(120, 100%, 40%);">+  data->header.type = 127;</span><br><span style="color: hsl(120, 100%, 40%);">+  data->header.length = sizeof(*data);</span><br><span style="color: hsl(120, 100%, 40%);">+  data->header.handle = handle;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(*buf + len + sizeof(*data), 0, 2);  /* double terminator */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return total_len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * vpd_append_type241 - append type 241 (binary blob pointer) structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @handle:  handle for this structure</span><br><span style="color: hsl(120, 100%, 40%);">+ * @buf:  buffer to append to</span><br><span style="color: hsl(120, 100%, 40%);">+ * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * @vendor:  blob vendor string</span><br><span style="color: hsl(120, 100%, 40%);">+ * @desc:  blob description string</span><br><span style="color: hsl(120, 100%, 40%);">+ * @variant:  blob variant string</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns total size of newly re-sized buffer if successful</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns <0 to indicate failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_append_type241(uint16_t handle, uint8_t **buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                       size_t len, const char *uuid, uint32_t offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                       uint32_t size, const char *vendor,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const char *desc, const char *variant)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_header *header;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_table_binary_blob_pointer *data;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *string_ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t struct_len, total_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int string_index = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* FIXME: Add sanity checking */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct_len = sizeof(struct vpd_header) +</span><br><span style="color: hsl(120, 100%, 40%);">+               sizeof(struct vpd_table_binary_blob_pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (vendor)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct_len += strlen(vendor) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (desc)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct_len += strlen(desc) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (variant)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct_len += strlen(variant) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct_len += 1;  /* structure terminator */</span><br><span style="color: hsl(120, 100%, 40%);">+  total_len = len + struct_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  *buf = realloc(*buf, total_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(*buf + len, 0, struct_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  header = (struct vpd_header *)(*buf + len);</span><br><span style="color: hsl(120, 100%, 40%);">+  data = (struct vpd_table_binary_blob_pointer *)</span><br><span style="color: hsl(120, 100%, 40%);">+            ((uint8_t *)header + sizeof(*header));</span><br><span style="color: hsl(120, 100%, 40%);">+  string_ptr = (char *)data + sizeof(*data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* fill in structure header details */</span><br><span style="color: hsl(120, 100%, 40%);">+  header->type = VPD_TYPE_BINARY_BLOB_POINTER;</span><br><span style="color: hsl(120, 100%, 40%);">+  header->length = sizeof(*header) + sizeof(*data);</span><br><span style="color: hsl(120, 100%, 40%);">+  header->handle = handle;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  data->struct_major_version = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  data->struct_minor_version = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (vendor) {</span><br><span style="color: hsl(120, 100%, 40%);">+    data->vendor = string_index;</span><br><span style="color: hsl(120, 100%, 40%);">+    string_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+    sprintf(string_ptr, "%s%c", vendor, '\0');</span><br><span style="color: hsl(120, 100%, 40%);">+    string_ptr += strlen(vendor) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (desc) {</span><br><span style="color: hsl(120, 100%, 40%);">+    data->description = string_index;</span><br><span style="color: hsl(120, 100%, 40%);">+    string_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+    sprintf(string_ptr, "%s%c", desc, '\0');</span><br><span style="color: hsl(120, 100%, 40%);">+    string_ptr += strlen(desc) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  data->major_version = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+  data->minor_version = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (variant) {</span><br><span style="color: hsl(120, 100%, 40%);">+    data->variant = string_index;</span><br><span style="color: hsl(120, 100%, 40%);">+    string_index++;</span><br><span style="color: hsl(120, 100%, 40%);">+    sprintf(string_ptr, "%s%c", variant, '\0');</span><br><span style="color: hsl(120, 100%, 40%);">+    string_ptr += strlen(variant) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(&data->reserved[0], 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (uuid_parse(uuid, &data->uuid[0]) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "invalid UUID \"%s\" specified\n", uuid);</span><br><span style="color: hsl(120, 100%, 40%);">+    goto vpd_create_type241_fail;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  data->offset = offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  data->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return total_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_create_type241_fail:</span><br><span style="color: hsl(120, 100%, 40%);">+  return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * vpd_type241_size - return the size of type 241 structure table.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Type 241 structure contains 3 variant length of string at end of table.</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is non-trival to get the length by sizeof(vpd_table_binary_blob_pointer).</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function can help by adding 3 strlen(NULL-terminated string).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @header:  pointer to the start address of this structure table.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns total size of this structure table.</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns <0 to indicate failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int vpd_type241_size(struct vpd_header *header) {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *ptr = (uint8_t*)header;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *str = (char*)ptr + header->length;</span><br><span style="color: hsl(120, 100%, 40%);">+  int length = sizeof(struct vpd_header) +</span><br><span style="color: hsl(120, 100%, 40%);">+               sizeof(struct vpd_table_binary_blob_pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Sanity check */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (header->type != VPD_TYPE_BINARY_BLOB_POINTER) return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Three variant-length strings are following. */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < 3; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+    int len = strlen(str) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    length += len;</span><br><span style="color: hsl(120, 100%, 40%);">+    str += len;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Additional null(0) to indicate end of set, so called structure terminator.</span><br><span style="color: hsl(120, 100%, 40%);">+   * Refer to SMBIOS spec 3.1.3 Text Strings.</span><br><span style="color: hsl(120, 100%, 40%);">+   * However, in VPD 1.x, the mosys would generate a buggy type 241 structure,</span><br><span style="color: hsl(120, 100%, 40%);">+   * which missed the terminator. See mosys between r169 and r211.</span><br><span style="color: hsl(120, 100%, 40%);">+   * The workaround is simple, when counting VPD 241 length, look at the byte</span><br><span style="color: hsl(120, 100%, 40%);">+   * byte after variant string. If it is 0x00, means it's the structure</span><br><span style="color: hsl(120, 100%, 40%);">+   * terminator. If non-zero, then it must be the next table type.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ptr[length] == 0) length++;  /* increase only if this is terminator. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return length;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void vpd_free_table(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *foo = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* clean-up is trivially simple, for now... */</span><br><span style="color: hsl(120, 100%, 40%);">+  free(foo);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/lib_vpd_test.c b/util/vpd/lib/lib_vpd_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..3ad8679</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/lib_vpd_test.c</span><br><span>@@ -0,0 +1,381 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2013 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  TEST_OK = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  TEST_FAIL = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define CU8 (const uint8_t *)  /* for compiler warning on sign bit */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testEncodeLen() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char output[10];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* fail cases */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_INVALID == encodeLen(-1, output, 0, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_OVERFLOW == encodeLen(0x7f, output, 0, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* success case - 1 byte output, all zeros */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeLen(0x00, output, 1, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(1 == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x00 == output[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* success case - 1 byte output */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeLen(0x7f, output, 1, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(1 == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x7f == output[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* 2 bytes of output */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_OVERFLOW == encodeLen(0x80, output, 1, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  /* success */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeLen(0x80, output, 2, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(2 == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x81 == output[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x00 == output[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* 3 bytes of output */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 0, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 1, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 2, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  /* success */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeLen(0x100040, output, 3, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(3 == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0xc0 == output[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x80 == output[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(0x40 == output[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDecodeLen() {</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t length;</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t consumed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* max_len is 0. No more char in string. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x00 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_ERR_OVERFLOW == decodeLen(0, encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* just decode one byte */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x00 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == sizeof(encoded));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* just decode one byte */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x7F };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == sizeof(encoded));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0x7F);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* more bit is set, but reachs end of string. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x80 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_ERR_OVERFLOW == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* decode 2 bytes, but reachs end of string. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x81, 0x02 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_ERR_OVERFLOW == decodeLen(1, encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* more bit is set, but reachs end of string. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x81, 0x82 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_ERR_OVERFLOW == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* decode 2 bytes, normal case */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x81, 0x02 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == sizeof(encoded));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0x82);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* decode 2 bytes, normal case (bot reach end of string). */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0xFF, 0x7F, 0xFF };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0x3FFF);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* weird case, but still valid. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x80, 0x00 };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == sizeof(encoded));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  { /* test max length */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t encoded[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F };</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(consumed == sizeof(encoded));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(length == 0x7FFFFFFF);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testEncodeVpdString() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, 'K', 'E', 'Y',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x05, 'V', 'A', 'L', 'U', 'E',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK ==</span><br><span style="color: hsl(120, 100%, 40%);">+         encodeVpdString(CU8"KEY", CU8"VALUE",</span><br><span style="color: hsl(120, 100%, 40%);">+                         VPD_AS_LONG_AS, sizeof(buf), buf, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testEncodeVpdStringPadding() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, 'K', 'E', 'Y',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeVpdString(CU8"KEY", CU8"VALUE",</span><br><span style="color: hsl(120, 100%, 40%);">+                                   8, sizeof(buf), buf, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testEncodeMultiStrings() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, 'M', 'A', 'C',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x08, '0', '1', '2', '3', '4', '5', '6', '7',</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x07, 'P', 'r', 'o', 'd', '/', 'I', 'd',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x0c, 'M', 'a', 'r', 'i', 'o', '0', '9', '2', '8', '4', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeVpdString(CU8"MAC", CU8"01234567",</span><br><span style="color: hsl(120, 100%, 40%);">+                                   0x08, sizeof(buf), buf, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == encodeVpdString(CU8"Prod/Id", CU8"Mario09284",</span><br><span style="color: hsl(120, 100%, 40%);">+                                   0x0c, sizeof(buf), buf, &generated));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testContainer() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, 'K', 'E', 'Y',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"KEY", CU8"VALUE", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  encodeContainer(&container, sizeof(buf), buf, &generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Based on previous test cases:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * KEY=VALUE --> encode --> decode --> expected KEY=VALUE</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int testDecodeVpdString() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, 'K', 'E', 'Y',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int consumed = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == decodeToContainer(&container, sizeof(expected), expected,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     &consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == consumed);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  consumed = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  encodeContainer(&container, sizeof(buf), buf, &consumed);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == consumed);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, consumed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDeleteEmptyContainer() {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good for add */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDeleteFirstOfOne() {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* test the case that only one string in container. */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"FIRST"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL == findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good for add */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"SECOND", CU8"2", 12);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"SECOND", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDeleteFirstOfTwo() {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* add 2 and remove the first one */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"SECOND", CU8"2", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"FIRST"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL == findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"SECOND", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good for add */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 9);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDeleteSecondOfTwo() {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* add 2 and remove the last one */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"SECOND", CU8"2", 8);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"SECOND"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL == findString(&container, CU8"SECOND", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good for add */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"SECOND", CU8"2", 5);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"SECOND", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int testDeleteSecondOfThree() {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char expected[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x05, 'F', 'I', 'R', 'S', 'T',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x03, '1', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+    VPD_TYPE_STRING,</span><br><span style="color: hsl(120, 100%, 40%);">+    0x05, 'T', 'H', 'I', 'R', 'D',</span><br><span style="color: hsl(120, 100%, 40%);">+    0x04, '3', '\0', '\0', '\0',</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char buf[256];</span><br><span style="color: hsl(120, 100%, 40%);">+  int generated = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer container;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* add 3 and remove the middle one */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIRST", CU8"1", 3);</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"SECOND", CU8"2", 2);</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"THIRD", CU8"3", 4);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"SECOND"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FIRST", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL == findString(&container, CU8"SECOND", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"THIRD", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* expect the middle one is removed. */</span><br><span style="color: hsl(120, 100%, 40%);">+  encodeContainer(&container, sizeof(buf), buf, &generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(sizeof(expected) == generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(!memcmp(expected, buf, generated));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good if we delete all */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"THIRD"));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(VPD_OK == deleteKey(&container, CU8"FIRST"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* still good for add */</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FORTH", CU8"4", 4);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FORTH", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(&container, CU8"FIFTH", CU8"5", 5);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(NULL != findString(&container, CU8"FIFTH", NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("[PASS] %s()\n", __FUNCTION__);</span><br><span style="color: hsl(120, 100%, 40%);">+  return TEST_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main() {</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testEncodeLen());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDecodeLen());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testEncodeVpdString());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testEncodeVpdStringPadding());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testEncodeMultiStrings());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testContainer());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDecodeVpdString());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDeleteEmptyContainer());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDeleteFirstOfOne());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDeleteFirstOfTwo());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDeleteSecondOfTwo());</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(TEST_OK == testDeleteSecondOfThree());</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("SUCCESS!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/math.c b/util/vpd/lib/math.c</span><br><span>new file mode 100644</span><br><span>index 0000000..c5b8063</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/math.c</span><br><span>@@ -0,0 +1,126 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2010 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * as published by the Free Software Foundation; either version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * math.c: implementations of some numerical utilities</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/stat.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/math.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * ctz - count trailing zeros</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @u:  Bit vector to count trailing zeros in.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Counts bit positions of lower significance than that of the least significant</span><br><span style="color: hsl(120, 100%, 40%);">+ * bit set. Based off of an algorithm from:</span><br><span style="color: hsl(120, 100%, 40%);">+ * http://graphics.stanford.edu/~seander/bithacks.html</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns count of trailing zeros</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ctz(unsigned long long int u)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int num_zeros;</span><br><span style="color: hsl(120, 100%, 40%);">+  union {</span><br><span style="color: hsl(120, 100%, 40%);">+    float f;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+  } alias;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (u == 0)   /* The algorithm will return -127 on this condition */</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  alias.f = (float)(u & (~u + 1));</span><br><span style="color: hsl(120, 100%, 40%);">+  num_zeros = (alias.i >> 23) - 0x7f;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return num_zeros;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * logbase2 - Return log base 2 of the absolute value of n (2^r = abs(n)) of an</span><br><span style="color: hsl(120, 100%, 40%);">+ * integer by using a cast to float method (Requires IEEE-754).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note: We could just use log2() but that would require messing with our</span><br><span style="color: hsl(120, 100%, 40%);">+ * compilation and linking options and hacking around the n = 0 case in other</span><br><span style="color: hsl(120, 100%, 40%);">+ * areas of the code.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @n:  The number to find the log base 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns log2(n) if successful</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int logbase2(int n)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  float f;</span><br><span style="color: hsl(120, 100%, 40%);">+  int r;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* This algorithm fails (Returns negative infinity) if n = 0. We'll be</span><br><span style="color: hsl(120, 100%, 40%);">+   * using it mostly in the context of CPU numbers, so we'll take the</span><br><span style="color: hsl(120, 100%, 40%);">+   * liberty of returning 0 instead of aborting */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (n == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  f = (float)n;</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(&r, &f, sizeof(n));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Isolate exponent and un-bias the exponent (Subtract +128) */</span><br><span style="color: hsl(120, 100%, 40%);">+  r = ((r & 0x7F800000) >> 23) - 0x80;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return r + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * rolling8_csum  -  Bytewise rolling summation "checksum" of a buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @buf:  buffer to sum</span><br><span style="color: hsl(120, 100%, 40%);">+ * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t rolling8_csum(uint8_t *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < len; ++i)</span><br><span style="color: hsl(120, 100%, 40%);">+    sum += buf[i];</span><br><span style="color: hsl(120, 100%, 40%);">+  return sum;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+  * zero8_csum - Calculates 8-bit zero-sum checksum</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * @buf:  input buffer</span><br><span style="color: hsl(120, 100%, 40%);">+  * @len:  length of buffer</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * The summation of the bytes in the array and the csum will equal zero</span><br><span style="color: hsl(120, 100%, 40%);">+  * for 8-bit data size.</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+  * returns checksum to indicate success</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t zero8_csum(uint8_t *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *u = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t csum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  while (u < buf + len) {</span><br><span style="color: hsl(120, 100%, 40%);">+    csum += *u;</span><br><span style="color: hsl(120, 100%, 40%);">+    u++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return (0x100 - csum);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/vpd_container.c b/util/vpd/lib/vpd_container.c</span><br><span>new file mode 100644</span><br><span>index 0000000..78f8e15</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/vpd_container.c</span><br><span>@@ -0,0 +1,435 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef MIN</span><br><span style="color: hsl(120, 100%, 40%);">+#define MIN(a, b) ((a < b) ? a : b)</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Container helpers</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+void initContainer(struct PairContainer *container) {</span><br><span style="color: hsl(120, 100%, 40%);">+  container->first = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns the pointer to the 'key' entry.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns NULL if the key is not found in 'container'.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If 'prev_next' is not NULL, findString() stores the address of the "next"</span><br><span style="color: hsl(120, 100%, 40%);">+ * member of the StringPair prior to the returned StringPair (the special case</span><br><span style="color: hsl(120, 100%, 40%);">+ * is &container->first if first StringPair matches 'key'). This is for linked</span><br><span style="color: hsl(120, 100%, 40%);">+ * list manipulation. If 'prev_next' is NULL, findString() would just ignore</span><br><span style="color: hsl(120, 100%, 40%);">+ * it.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct StringPair *findString(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                              const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                              struct StringPair ***prev_next) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (prev_next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    *prev_next = &container->first;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (current = container->first; current; current = current->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!strcmp((char*)key, (char*)current->key)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      return current;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    if (prev_next) {</span><br><span style="color: hsl(120, 100%, 40%);">+      *prev_next = &current->next;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Just a helper function for setString() */</span><br><span style="color: hsl(120, 100%, 40%);">+static void fillStringPair(struct StringPair *pair,</span><br><span style="color: hsl(120, 100%, 40%);">+                           const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                           const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+                           const int pad_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  pair->key = malloc(strlen((char*)key) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(pair->key);</span><br><span style="color: hsl(120, 100%, 40%);">+  strcpy((char*)pair->key, (char*)key);</span><br><span style="color: hsl(120, 100%, 40%);">+  pair->value = malloc(strlen((char*)value) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+  strcpy((char*)pair->value, (char*)value);</span><br><span style="color: hsl(120, 100%, 40%);">+  pair->pad_len = pad_len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* If key is already existed in container, its value will be replaced.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If not existed, creates new entry in container.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void setString(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+               const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+               const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+               const int pad_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *found;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  found = findString(container, key, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (found) {</span><br><span style="color: hsl(120, 100%, 40%);">+    free(found->key);</span><br><span style="color: hsl(120, 100%, 40%);">+    free(found->value);</span><br><span style="color: hsl(120, 100%, 40%);">+    fillStringPair(found, key, value, pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    struct StringPair *new_pair = malloc(sizeof(struct StringPair));</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(new_pair);</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(new_pair, 0, sizeof(struct StringPair));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    fillStringPair(new_pair, key, value, pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* append this pair to the end of list. to keep the order */</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((found = container->first)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      while (found->next) found = found->next;</span><br><span style="color: hsl(120, 100%, 40%);">+      found->next = new_pair;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      container->first = new_pair;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    new_pair->next = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Remove a key.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns VPD_OK if deleted successfully. Otherwise, VPD_FAIL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t deleteKey(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const uint8_t *key) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *found, **prev_next;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  found = findString(container, key, &prev_next);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (found) {</span><br><span style="color: hsl(120, 100%, 40%);">+    free(found->key);</span><br><span style="color: hsl(120, 100%, 40%);">+    free(found->value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* remove the 'found' from the linked list. */</span><br><span style="color: hsl(120, 100%, 40%);">+    assert(prev_next);</span><br><span style="color: hsl(120, 100%, 40%);">+    *prev_next = found->next;</span><br><span style="color: hsl(120, 100%, 40%);">+    free(found);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns number of pairs in container.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int lenOfContainer(const struct PairContainer *container) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int count;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (count = 0, current = container->first;</span><br><span style="color: hsl(120, 100%, 40%);">+       current;</span><br><span style="color: hsl(120, 100%, 40%);">+       count++, current = current->next);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return count;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Iterate src container and setString() in dst.</span><br><span style="color: hsl(120, 100%, 40%);">+ * so that if key is duplicate, the one in dst is overwritten.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void mergeContainer(struct PairContainer *dst,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct PairContainer *src) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (current = src->first; current; current = current->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    setString(dst, current->key, current->value, current->pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int subtractContainer(struct PairContainer *dst,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const struct PairContainer *src) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+  int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (current = src->first; current; current = current->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK == deleteKey(dst, current->key))</span><br><span style="color: hsl(120, 100%, 40%);">+      count++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return count;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeContainer(const struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (current = container->first; current; current = current->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != encodeVpdString(current->key,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  current->value,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  current->pad_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  generated)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t callbackDecodeToContainer(const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           int32_t key_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           int32_t value_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           void *arg) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct PairContainer *container = (struct PairContainer*)arg;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *key_string = (uint8_t*)malloc(key_len + 1),</span><br><span style="color: hsl(120, 100%, 40%);">+          *value_string = (uint8_t*)malloc(value_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(key_string && value_string);</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(key_string, key, key_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(value_string, value, value_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  key_string[key_len] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+  value_string[value_len] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+  setString(container, key_string, value_string, value_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeToContainer(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const uint8_t *input_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                            int32_t *consumed) {</span><br><span style="color: hsl(120, 100%, 40%);">+  return decodeVpdString(max_len, input_buf, consumed,</span><br><span style="color: hsl(120, 100%, 40%);">+                         callbackDecodeToContainer, (void*)container);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t setContainerFilter(struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                             const uint8_t *filter) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *str;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (str = container->first; str; str = str->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (filter) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /*</span><br><span style="color: hsl(120, 100%, 40%);">+       * TODO(yjlou):</span><br><span style="color: hsl(120, 100%, 40%);">+       * Now, we treat the inputing filter string as plain string.</span><br><span style="color: hsl(120, 100%, 40%);">+       * Will support regular expression syntax in future if needed.</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (strcmp((char*)str->key, (char*)filter)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        str->filter_out = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      str->filter_out = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A helper function to append a sequence of bytes to the given buffer.  If</span><br><span style="color: hsl(120, 100%, 40%);">+ * the buffer size is not enough, this function will return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+ * otherwise it will return VPD_OK.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t _appendToBuf(const void *buf_to_append,</span><br><span style="color: hsl(120, 100%, 40%);">+                              int len,</span><br><span style="color: hsl(120, 100%, 40%);">+                              const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                              uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                              int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated + len > max_buf_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(&buf[*generated], buf_to_append, len);</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated += len;</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A helper function to resolve the number of bytes to be exported for the</span><br><span style="color: hsl(120, 100%, 40%);">+ * value field of an instance of StringPair.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int _getStringPairValueLen(const struct StringPair *str) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int len = strlen((const char*)(str->value));</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_AS_LONG_AS == str->pad_len ? len : MIN(str->pad_len, len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* A helper function to export an instance of StringPair to the given buffer. */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t _exportStringPairKeyValue(const struct StringPair *str,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  const void *strs[5] = {"\"", str->key, "\"=\"", str->value, "\"\n"};</span><br><span style="color: hsl(120, 100%, 40%);">+  const int lens[5] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      1, strlen((const char*)str->key), 3, _getStringPairValueLen(str), 2};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  int retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < sizeof(lens) / sizeof(int); ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = _appendToBuf(strs[i], lens[i], max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+      break;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A helper function to escape the special character in a string and then append</span><br><span style="color: hsl(120, 100%, 40%);">+ * the result into the buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t _appendToBufWithShellEscape(const char *str_to_export,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int len = strlen(str_to_export);</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+  int retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < len; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if ('\'' == str_to_export[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = _appendToBuf("'\"'\"'", 5, max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = _appendToBuf(str_to_export + i, 1,</span><br><span style="color: hsl(120, 100%, 40%);">+                            max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A helper function to export an instance of StringPair to the given buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * as the arguments for the vpd commandline tool.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t _exportStringPairAsParameter(const struct StringPair *str,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    char extra_params[32];</span><br><span style="color: hsl(120, 100%, 40%);">+    snprintf(extra_params, sizeof(extra_params), "    -p %d -s ", str->pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = _appendToBuf(extra_params, strlen(extra_params),</span><br><span style="color: hsl(120, 100%, 40%);">+                          max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated + 1 > max_buf_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[(*generated)++] = '\'';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = _appendToBufWithShellEscape(</span><br><span style="color: hsl(120, 100%, 40%);">+      (const char*)str->key, max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated + 1 > max_buf_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[(*generated)++] = '=';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = _appendToBufWithShellEscape(</span><br><span style="color: hsl(120, 100%, 40%);">+      (const char*)str->value, max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = _appendToBuf("' \\\n", 4, max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A helper function to export an instance of StringPair to the given buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * in a null terminate format, i.e. "<key>=<value>\0"</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t _exportStringPairNullTerminate(const struct StringPair *str,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = _appendToBuf(str->key, strlen((const char*)str->key),</span><br><span style="color: hsl(120, 100%, 40%);">+                        max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated + 1 > max_buf_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[(*generated)++] = '=';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = _appendToBuf(str->value, _getStringPairValueLen(str),</span><br><span style="color: hsl(120, 100%, 40%);">+                        max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated + 1 > max_buf_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[(*generated)++] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Export the value field of the instance of StringPair. */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t exportStringValue(const struct StringPair *str,</span><br><span style="color: hsl(120, 100%, 40%);">+                            const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                            uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                            int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(generated);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return _appendToBuf(str->value, _getStringPairValueLen(str),</span><br><span style="color: hsl(120, 100%, 40%);">+                      max_buf_len, buf, generated);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Export the container content with human-readable text. */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t exportContainer(const int export_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint8_t *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *str;</span><br><span style="color: hsl(120, 100%, 40%);">+  int index;</span><br><span style="color: hsl(120, 100%, 40%);">+  int retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  index = *generated;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (str = container->first; str; str = str->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (str->filter_out)</span><br><span style="color: hsl(120, 100%, 40%);">+      continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_EXPORT_KEY_VALUE == export_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = _exportStringPairKeyValue(str, max_buf_len, buf, &index);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (VPD_EXPORT_AS_PARAMETER == export_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = _exportStringPairAsParameter(str, max_buf_len, buf, &index);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (VPD_EXPORT_NULL_TERMINATE == export_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = _exportStringPairNullTerminate(str, max_buf_len, buf, &index);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* this block shouldn't be reached */</span><br><span style="color: hsl(120, 100%, 40%);">+      assert(0);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated = index;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void destroyContainer(struct PairContainer *container) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct StringPair *current;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (current = container->first; current;) {</span><br><span style="color: hsl(120, 100%, 40%);">+    struct StringPair *next;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (current->key) free(current->key);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (current->value) free(current->value);</span><br><span style="color: hsl(120, 100%, 40%);">+    next = current->next;</span><br><span style="color: hsl(120, 100%, 40%);">+    free(current);</span><br><span style="color: hsl(120, 100%, 40%);">+    current = next;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/vpd_decode.c b/util/vpd/lib/vpd_decode.c</span><br><span>new file mode 100644</span><br><span>index 0000000..7f266fb</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/vpd_decode.c</span><br><span>@@ -0,0 +1,95 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeLen(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *in,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *length,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *decoded_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t more;</span><br><span style="color: hsl(120, 100%, 40%);">+  int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(length);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(decoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  *length = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  do {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (i >= max_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+    more = in[i] & 0x80;</span><br><span style="color: hsl(120, 100%, 40%);">+    *length <<= 7;</span><br><span style="color: hsl(120, 100%, 40%);">+    *length |= in[i] & 0x7f;</span><br><span style="color: hsl(120, 100%, 40%);">+    ++i;</span><br><span style="color: hsl(120, 100%, 40%);">+  } while (more);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  *decoded_len = i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Sequentially decodes type, key, and value.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t decodeVpdString(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *input_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *consumed,</span><br><span style="color: hsl(120, 100%, 40%);">+    VpdDecodeCallback callback,</span><br><span style="color: hsl(120, 100%, 40%);">+    void *callback_arg) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int type;</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t key_len, value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t decoded_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  const uint8_t *key, *value;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* type */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*consumed >= max_len)</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  type = input_buf[*consumed];</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (type) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case VPD_TYPE_INFO:</span><br><span style="color: hsl(120, 100%, 40%);">+    case VPD_TYPE_STRING:</span><br><span style="color: hsl(120, 100%, 40%);">+      (*consumed)++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* key */</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = decodeLen(max_len - *consumed, &input_buf[*consumed],</span><br><span style="color: hsl(120, 100%, 40%);">+                         &key_len, &decoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (VPD_OK != retval)</span><br><span style="color: hsl(120, 100%, 40%);">+        return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (*consumed + decoded_len >= max_len)</span><br><span style="color: hsl(120, 100%, 40%);">+        return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      *consumed += decoded_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      key = &input_buf[*consumed];</span><br><span style="color: hsl(120, 100%, 40%);">+      *consumed += key_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* value */</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = decodeLen(max_len - *consumed, &input_buf[*consumed],</span><br><span style="color: hsl(120, 100%, 40%);">+                         &value_len, &decoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (VPD_OK != retval)</span><br><span style="color: hsl(120, 100%, 40%);">+        return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (*consumed + decoded_len > max_len)</span><br><span style="color: hsl(120, 100%, 40%);">+        return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      *consumed += decoded_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      value = &input_buf[*consumed];</span><br><span style="color: hsl(120, 100%, 40%);">+      *consumed += value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (type == VPD_TYPE_STRING)</span><br><span style="color: hsl(120, 100%, 40%);">+        return callback(key, key_len, value, value_len, callback_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    default:</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      break;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/lib/vpd_encode.c b/util/vpd/lib/vpd_encode.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b8a35d1</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/lib/vpd_encode.c</span><br><span>@@ -0,0 +1,136 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Encodes the len into multiple bytes with the following format.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    7   6 ............ 0</span><br><span style="color: hsl(120, 100%, 40%);">+ *  +----+------------------+</span><br><span style="color: hsl(120, 100%, 40%);">+ *  |More|      Length      |  ...</span><br><span style="color: hsl(120, 100%, 40%);">+ *  +----+------------------+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns fail if the buffer is not long enough.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeLen(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *encode_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int32_t max_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t *encoded_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int shifting;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int reversed_7bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int out_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(encoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (len < 0) return VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+  shifting = len;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* reverse the len for every 7-bit. The little endian. */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (*encoded_len = 0; shifting; (*encoded_len)++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    reversed_7bits = (reversed_7bits << 7) | (shifting & 0x7f);</span><br><span style="color: hsl(120, 100%, 40%);">+    shifting >>= 7;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*encoded_len > max_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!*encoded_len) *encoded_len = 1;  /* output at least 1 byte */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Output in reverse order, now big endian. */</span><br><span style="color: hsl(120, 100%, 40%);">+  while (out_index < *encoded_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* always set MORE flag */</span><br><span style="color: hsl(120, 100%, 40%);">+    encode_buf[out_index++] = 0x80 | (reversed_7bits & 0x7f);</span><br><span style="color: hsl(120, 100%, 40%);">+    reversed_7bits >>= 7;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  encode_buf[out_index - 1] &= 0x7f;  /* clear the MORE flag in last byte */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*  Encodes the terminator.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeVpdTerminator(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int max_buffer_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int *generated_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(generated_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated_len >= max_buffer_len) return VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += *generated_len;  /* move cursor to end of string */</span><br><span style="color: hsl(120, 100%, 40%);">+  *(output_buf++) = VPD_TYPE_TERMINATOR;</span><br><span style="color: hsl(120, 100%, 40%);">+  (*generated_len)++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Encodes a string with padding support. */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t encodeVpdString(</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *key,</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *value,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int pad_value_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int max_buffer_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t *output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int *generated_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int key_len, value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int ret_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int pad_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(generated_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  key_len = strlen((char*)key);</span><br><span style="color: hsl(120, 100%, 40%);">+  value_len = strlen((char*)value);</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += *generated_len;  /* move cursor to end of string */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode type */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated_len >= max_buffer_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  *(output_buf++) = VPD_TYPE_STRING;</span><br><span style="color: hsl(120, 100%, 40%);">+  (*generated_len)++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode key len */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != encodeLen(key_len, output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          max_buffer_len - *generated_len, &ret_len))</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += ret_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated_len += ret_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode key string */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated_len + key_len > max_buffer_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(output_buf, key, key_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += key_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated_len += key_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* count padding length */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (pad_value_len != VPD_AS_LONG_AS) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (value_len < pad_value_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+      pad_len = pad_value_len - value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      value_len = pad_value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode value len */</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = encodeLen(value_len + pad_len, output_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                     max_buffer_len - *generated_len, &ret_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval)</span><br><span style="color: hsl(120, 100%, 40%);">+    return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += ret_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated_len += ret_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode value string */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated_len + value_len > max_buffer_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(output_buf, value, value_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated_len += value_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode padding (if applicable) */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*generated_len + pad_len > max_buffer_len) return VPD_ERR_OVERFLOW;</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(output_buf, 0, pad_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  output_buf += pad_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated_len += pad_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/util/vpd/vpd.c b/util/vpd/vpd.c</span><br><span>new file mode 100644</span><br><span>index 0000000..bdf948e</span><br><span>--- /dev/null</span><br><span>+++ b/util/vpd/vpd.c</span><br><span>@@ -0,0 +1,1202 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ctype.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <getopt.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/stat.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <uuid/uuid.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/flashrom.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/fmap.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/lib_smbios.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/vpd.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "lib/vpd_tables.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The buffer length. Right now the VPD partition size on flash is 128KB. */</span><br><span style="color: hsl(120, 100%, 40%);">+#define BUF_LEN (128 * 1024)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The comment shown in the begin of --sh output */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SH_COMMENT                                                      \</span><br><span style="color: hsl(120, 100%, 40%);">+  "#\n"                                                                 \</span><br><span style="color: hsl(120, 100%, 40%);">+  "# Prepend 'vpd -O' before this text to always reset VPD content.\n"  \</span><br><span style="color: hsl(120, 100%, 40%);">+  "# Append more -s at end to set additional key/values.\n"             \</span><br><span style="color: hsl(120, 100%, 40%);">+  "# Or an empty line followed by other commands.\n"                    \</span><br><span style="color: hsl(120, 100%, 40%);">+  "#\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Forward reference(s) */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t *readFileContent(const char* filename, uint32_t *filesize);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Linked list to track temporary files</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct TempfileNode {</span><br><span style="color: hsl(120, 100%, 40%);">+  char *filename;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct TempfileNode *next;</span><br><span style="color: hsl(120, 100%, 40%);">+} *tempfile_list = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum FileFlag {</span><br><span style="color: hsl(120, 100%, 40%);">+  HAS_SPD = (1 << 0),</span><br><span style="color: hsl(120, 100%, 40%);">+  HAS_VPD_2_0 = (1 << 1),</span><br><span style="color: hsl(120, 100%, 40%);">+  HAS_VPD_1_2 = (1 << 2),</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO(yjlou): refine those variables in main() to here:</span><br><span style="color: hsl(120, 100%, 40%);">+   *              write_back_to_flash, overwrite_it, modified. */</span><br><span style="color: hsl(120, 100%, 40%);">+} file_flag = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 2 containers:</span><br><span style="color: hsl(120, 100%, 40%);">+ *   file:      stores decoded pairs from file.</span><br><span style="color: hsl(120, 100%, 40%);">+ *   argument:  stores parsed pairs from command arguments.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct PairContainer file;</span><br><span style="color: hsl(120, 100%, 40%);">+struct PairContainer set_argument;</span><br><span style="color: hsl(120, 100%, 40%);">+struct PairContainer del_argument;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int export_type = VPD_EXPORT_KEY_VALUE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The current padding length value.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Default: VPD_AS_LONG_AS</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int pad_value_len = VPD_AS_LONG_AS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The output buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t buf[BUF_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+int buf_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+int max_buf_len = sizeof(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The EPS base address used to fill the EPS table entry.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the VPD partition can be found in fmap, this points to the starting</span><br><span style="color: hsl(120, 100%, 40%);">+ * offset of VPD partition. If not found, this is used to be the base address</span><br><span style="color: hsl(120, 100%, 40%);">+ * to increase SPD and VPD 2.0 offset fields.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * User can overwrite this by -E argument.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define UNKNOWN_EPS_BASE ((uint32_t)-1)</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t eps_base = UNKNOWN_EPS_BASE;</span><br><span style="color: hsl(120, 100%, 40%);">+int eps_base_force_specified = 0;  /* a bool value to indicate if -E argument</span><br><span style="color: hsl(120, 100%, 40%);">+                                    * is given. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* the fmap name of VPD. */</span><br><span style="color: hsl(120, 100%, 40%);">+char fmap_vpd_area_name[FMAP_STRLEN] = "RO_VPD";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* If found_vpd, replace the VPD partition when saveFile().</span><br><span style="color: hsl(120, 100%, 40%);">+ * If not found, always create new file when saveFlie(). */</span><br><span style="color: hsl(120, 100%, 40%);">+int found_vpd = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* The VPD partition offset and size in buf[]. The whole partition includes:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   SMBIOS EPS</span><br><span style="color: hsl(120, 100%, 40%);">+ *   SMBIOS tables[]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   SPD</span><br><span style="color: hsl(120, 100%, 40%);">+ *   VPD 2.0 data</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t vpd_offset = 0, vpd_size;  /* The whole partition */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Below offset are related to vpd_offset and assume positive.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Those are used in saveFile() to write back data. */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t eps_offset = 0;  /* EPS's starting address. Tables[] is following. */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t spd_offset = GOOGLE_SPD_OFFSET;  /* SPD address .*/</span><br><span style="color: hsl(120, 100%, 40%);">+off_t vpd_2_0_offset = GOOGLE_VPD_2_0_OFFSET;  /* VPD 2.0 data address. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This points to the SPD data if it is availiable when loadFile().</span><br><span style="color: hsl(120, 100%, 40%);">+ * The memory is allocated in loadFile(), will be used in saveFile(),</span><br><span style="color: hsl(120, 100%, 40%);">+ * and freed at end of main(). */</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t *spd_data = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+int32_t spd_len = 256;  /* max value for DDR3 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Creates a temporary file and return the filename, or NULL for any failure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *myMkTemp() {</span><br><span style="color: hsl(120, 100%, 40%);">+  char tmp_file[] = "/tmp/vpd.flashrom.XXXXXX";</span><br><span style="color: hsl(120, 100%, 40%);">+  struct TempfileNode *node;</span><br><span style="color: hsl(120, 100%, 40%);">+  int fd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  fd = mkstemp(tmp_file);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (fd < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "mkstemp(%s) failed\n", tmp_file);</span><br><span style="color: hsl(120, 100%, 40%);">+    return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+  node = (struct TempfileNode*)malloc(sizeof(struct TempfileNode));</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(node);</span><br><span style="color: hsl(120, 100%, 40%);">+  node->next = tempfile_list;</span><br><span style="color: hsl(120, 100%, 40%);">+  node->filename = strdup(tmp_file);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(node->filename);</span><br><span style="color: hsl(120, 100%, 40%);">+  tempfile_list = node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return node->filename;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*  Erases all files created by myMkTemp</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void cleanTempFiles() {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct TempfileNode *node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  while (tempfile_list) {</span><br><span style="color: hsl(120, 100%, 40%);">+    node = tempfile_list;</span><br><span style="color: hsl(120, 100%, 40%);">+    tempfile_list = node->next;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (unlink(node->filename) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "warning: failed removing temporary file: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              node->filename);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    free(node->filename);</span><br><span style="color: hsl(120, 100%, 40%);">+    free(node);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*  Given the offset of blob block (related to the first byte of EPS) and</span><br><span style="color: hsl(120, 100%, 40%);">+ *  the size of blob, the is function generates an SMBIOS ESP.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t buildEpsAndTables(</span><br><span style="color: hsl(120, 100%, 40%);">+    const int size_blob,</span><br><span style="color: hsl(120, 100%, 40%);">+    const int max_buf_len,</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned char *buf,</span><br><span style="color: hsl(120, 100%, 40%);">+    int *generated) {</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_entry *eps;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char *table = NULL;          /* the structure table */</span><br><span style="color: hsl(120, 100%, 40%);">+  int table_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int num_structures = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(generated);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(eps_base != UNKNOWN_EPS_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  buf += *generated;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Generate type 241 - SPD data */</span><br><span style="color: hsl(120, 100%, 40%);">+  table_len = vpd_append_type241(0, &table, table_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_SPD_UUID,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 eps_base + GOOGLE_SPD_OFFSET,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 spd_len,  /* Max length for DDR3 */</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_SPD_VENDOR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_SPD_DESCRIPTION,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_SPD_VARIANT);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (table_len < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto error_1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  num_structures++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+   * TODO(hungte) Once most systems have been updated to support VPD_INFO</span><br><span style="color: hsl(120, 100%, 40%);">+   * record, we can remove the +sizeof(google_vpd_info) hack.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Generate type 241 - VPD 2.0 */</span><br><span style="color: hsl(120, 100%, 40%);">+  table_len = vpd_append_type241(1, &table, table_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_VPD_2_0_UUID,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 (eps_base + GOOGLE_VPD_2_0_OFFSET +</span><br><span style="color: hsl(120, 100%, 40%);">+                                  sizeof(struct google_vpd_info)),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 size_blob,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_VPD_2_0_VENDOR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_VPD_2_0_DESCRIPTION,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 GOOGLE_VPD_2_0_VARIANT);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (table_len < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto error_1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  num_structures++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Generate type 127 */</span><br><span style="color: hsl(120, 100%, 40%);">+  table_len = vpd_append_type127(2, &table, table_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (table_len < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto error_1;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  num_structures++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Generate EPS */</span><br><span style="color: hsl(120, 100%, 40%);">+  eps = vpd_create_eps(table_len, num_structures, eps_base);</span><br><span style="color: hsl(120, 100%, 40%);">+  if ((*generated + eps->entry_length) > max_buf_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto error_2;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Copy EPS back to buf */</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(buf, eps, eps->entry_length);</span><br><span style="color: hsl(120, 100%, 40%);">+  buf += eps->entry_length;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated += eps->entry_length;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Copy tables back to buf */</span><br><span style="color: hsl(120, 100%, 40%);">+  if ((*generated + table_len) > max_buf_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto error_2;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(buf, table, table_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  buf += table_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  *generated += table_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+error_2:</span><br><span style="color: hsl(120, 100%, 40%);">+  free(eps);</span><br><span style="color: hsl(120, 100%, 40%);">+error_1:</span><br><span style="color: hsl(120, 100%, 40%);">+  free(table);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int isbase64(uint8_t c)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return isalnum(c) || (c == '+') || (c == '/') || (c == '=');</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t *read_string_from_file(const char *file_name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t i, j, file_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *file_buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  file_buffer = readFileContent(file_name, &file_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!file_buffer)</span><br><span style="color: hsl(120, 100%, 40%);">+    return NULL; /* The error has been reported already. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+   * Is the contents a proper base64 blob? Verify it and drop EOL characters</span><br><span style="color: hsl(120, 100%, 40%);">+   * along the way, this will help when displaying the contents.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0, j = 0; i < file_size; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t c = file_buffer[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((c == 0xa) || (c == 0xd))</span><br><span style="color: hsl(120, 100%, 40%);">+      continue;  /* Skip EOL characters */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!isbase64(c)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] file %s is not in base64 format (%c at %d)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              file_name, c, i);</span><br><span style="color: hsl(120, 100%, 40%);">+      free(file_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+      return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    file_buffer[j++] = c;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  file_buffer[j] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return (uint8_t *)file_buffer;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Check if given key name is compliant to recommended format.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static vpd_err_t checkKeyName(const uint8_t *name) {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char c;</span><br><span style="color: hsl(120, 100%, 40%);">+  while ((c = *name++)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(isalnum(c) || c == '_' || c == '.')) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] VPD key name does not allow char [%c].\n", c);</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_ERR_PARAM;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Given a key=value string, this function parses it and adds to arugument</span><br><span style="color: hsl(120, 100%, 40%);">+ * pair container. The 'value' can be stored in a base64 format file, in this</span><br><span style="color: hsl(120, 100%, 40%);">+ * case the value field is the file name.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t parseString(const uint8_t *string, int read_from_file) {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *key;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *value;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *file_contents = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  key = (uint8_t*)strdup((char*)string);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!key || key[0] == '\0' || key[0] == '=') {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (key) free(key);</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+   * Goes through the key string, and stops at the first '='.</span><br><span style="color: hsl(120, 100%, 40%);">+   * If '=' is not found, the whole string is the key and</span><br><span style="color: hsl(120, 100%, 40%);">+   * the value points to the end of string ('\0').</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (value = key; *value && *value != '='; value++);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*value == '=') {</span><br><span style="color: hsl(120, 100%, 40%);">+    *(value++) = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (read_from_file) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* 'value' in fact is a file name */</span><br><span style="color: hsl(120, 100%, 40%);">+      file_contents = read_string_from_file((const char *)value);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!file_contents) {</span><br><span style="color: hsl(120, 100%, 40%);">+        free(key);</span><br><span style="color: hsl(120, 100%, 40%);">+        return VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+      value = file_contents;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = checkKeyName(key);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (retval == VPD_OK)</span><br><span style="color: hsl(120, 100%, 40%);">+    setString(&set_argument, key, value, pad_value_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  free(key);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (file_contents)</span><br><span style="color: hsl(120, 100%, 40%);">+    free(file_contents);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Given an address, compare if it is SMBIOS signature ("_SM_"). */</span><br><span style="color: hsl(120, 100%, 40%);">+int isEps(const void* ptr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  return !memcmp(VPD_ENTRY_MAGIC, ptr, sizeof(VPD_ENTRY_MAGIC) - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO(yjlou): need more EPS sanity checks here. */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* There are two possible file content appearng here:</span><br><span style="color: hsl(120, 100%, 40%);">+ *   1. a full and complete BIOS file</span><br><span style="color: hsl(120, 100%, 40%);">+ *   2. a full but only VPD partition area is valid. (no fmap)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   3. a full BIOS, but VPD partition is blank.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The first case is easy. Just lookup the fmap and find out the VPD partition.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The second is harder. We try to search the SMBIOS signature (since others</span><br><span style="color: hsl(120, 100%, 40%);">+ * are blank). For the third, we just return and leave caller to read full</span><br><span style="color: hsl(120, 100%, 40%);">+ * content, including fmap info.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If found, vpd_offset and vpd_size are updated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t findVpdPartition(const uint8_t* read_buf, const uint32_t file_size,</span><br><span style="color: hsl(120, 100%, 40%);">+                     uint32_t* vpd_offset, uint32_t* vpd_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+  off_t sig_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct fmap *fmap;</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(read_buf);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(vpd_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(vpd_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* scan the file and find out the VPD partition. */</span><br><span style="color: hsl(120, 100%, 40%);">+  sig_offset = fmapFind(read_buf, file_size);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (-1 != sig_offset) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* FMAP signature is found, try to search the partition name in table. */</span><br><span style="color: hsl(120, 100%, 40%);">+    fmap = (struct fmap *)&read_buf[sig_offset];</span><br><span style="color: hsl(120, 100%, 40%);">+    for(i = 0; i < fmap->nareas; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fmapNormalizeAreaName(fmap->areas[i].name);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (FMAP_OK == fmapGetArea(fmap_vpd_area_name, fmap,</span><br><span style="color: hsl(120, 100%, 40%);">+                               vpd_offset, vpd_size)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      found_vpd = 1;  /* Mark found here then saveFile() knows where to</span><br><span style="color: hsl(120, 100%, 40%);">+                       * write back (vpd_offset, vpd_size). */</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] The VPD partition [%s] is not found.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              fmap_vpd_area_name);</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* The signature must be aligned to 16-byte. */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < file_size; i += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (isEps(&read_buf[i])) {</span><br><span style="color: hsl(120, 100%, 40%);">+      found_vpd = 1;  /* Mark found here then saveFile() knows where to</span><br><span style="color: hsl(120, 100%, 40%);">+                       * write back (vpd_offset, vpd_size). */</span><br><span style="color: hsl(120, 100%, 40%);">+      *vpd_offset = i;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* FIXME: We don't know the VPD partition size in this case.</span><br><span style="color: hsl(120, 100%, 40%);">+       *        However, return 4K should be safe enough now.</span><br><span style="color: hsl(120, 100%, 40%);">+       *        In the long term, this code block will be obscured. */</span><br><span style="color: hsl(120, 100%, 40%);">+      *vpd_size = 4096;</span><br><span style="color: hsl(120, 100%, 40%);">+      return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return VPD_ERR_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Load file content into memory.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns: NULL if file opens error or read error.</span><br><span style="color: hsl(120, 100%, 40%);">+ *          Others, pointer to the memory. The filesize is also returned.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note: it's caller's responsbility to free the memory.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t *readFileContent(const char* filename, uint32_t *filesize) {</span><br><span style="color: hsl(120, 100%, 40%);">+  FILE *fp;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *read_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(filename);</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(filesize);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!(fp = fopen(filename, "r"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+    return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  /* get file size */</span><br><span style="color: hsl(120, 100%, 40%);">+  fseek(fp, 0, SEEK_END);</span><br><span style="color: hsl(120, 100%, 40%);">+  *filesize = ftell(fp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* read file content */</span><br><span style="color: hsl(120, 100%, 40%);">+  fseek(fp, 0, SEEK_SET);</span><br><span style="color: hsl(120, 100%, 40%);">+  read_buf = malloc(*filesize + 1); /* Might need room for a \0. */</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(read_buf);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (*filesize != fread(read_buf, 1, *filesize, fp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] Reading file [%s] failed.\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+    return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  fclose(fp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return read_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t getVpdPartitionFromFullBios(uint32_t* offset, uint32_t* size) {</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *filename;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t buf_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  filename = myMkTemp();</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!filename) {</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (FLASHROM_OK != flashromFullRead(filename)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[WARN] Cannot read full BIOS.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_ERR_ROM_READ;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  assert((buf = readFileContent(filename, &buf_size)));</span><br><span style="color: hsl(120, 100%, 40%);">+  if (findVpdPartition(buf, buf_size, offset, size)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[WARN] Cannot get eps_base from full BIOS.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  free(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Below 2 functions are the helper functions for extract data from VPD 1.x</span><br><span style="color: hsl(120, 100%, 40%);">+ * binary-encoded structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note that the returning pointer is a static buffer. Thus the later call will</span><br><span style="color: hsl(120, 100%, 40%);">+ * destroy the former call's result.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t* extractString(const uint8_t* value, const int max_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  static uint8_t buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+  int copy_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* not longer than the buffer size */</span><br><span style="color: hsl(120, 100%, 40%);">+  copy_len = (max_len > sizeof(buf) - 1) ? sizeof(buf) - 1 : max_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(buf, value, copy_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[copy_len] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t* extractHex(const uint8_t* value, const int len) {</span><br><span style="color: hsl(120, 100%, 40%);">+  char tmp[4];  /* for a hex string */</span><br><span style="color: hsl(120, 100%, 40%);">+  static uint8_t buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+  int in, out;  /* in points to value[], while out points to buf[]. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  for (in = 0, out = 0;; ++in) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (out + 3 > sizeof(buf) - 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+      goto end_of_func;  /* no more buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    if (in >= len) {  /* no more input */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (out) --out;  /* remove the tailing colon */</span><br><span style="color: hsl(120, 100%, 40%);">+      goto end_of_func;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    sprintf(tmp, "%02x:", value[in]);</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(&buf[out], tmp, strlen(tmp));</span><br><span style="color: hsl(120, 100%, 40%);">+    out += strlen(tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+end_of_func:</span><br><span style="color: hsl(120, 100%, 40%);">+  buf[out] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t loadFile(const char *filename, struct PairContainer *container,</span><br><span style="color: hsl(120, 100%, 40%);">+             int overwrite_it) {</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t file_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *read_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *vpd_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_entry *eps;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t related_eps_base;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_header *header;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct vpd_table_binary_blob_pointer *data;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t spd_uuid[16], vpd_2_0_uuid[16], vpd_1_2_uuid[16];</span><br><span style="color: hsl(120, 100%, 40%);">+  int expected_handle;</span><br><span style="color: hsl(120, 100%, 40%);">+  int table_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int index;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!(read_buf = readFileContent(filename, &file_size))) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[WARN] Cannot LoadFile('%s'), that's fine.\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+    return VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (0 == findVpdPartition(read_buf, file_size, &vpd_offset, &vpd_size)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!eps_base_force_specified) {</span><br><span style="color: hsl(120, 100%, 40%);">+      eps_base = vpd_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* We cannot parse out the VPD partition address from given file.</span><br><span style="color: hsl(120, 100%, 40%);">+     * Then, try to read the whole BIOS chip. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t offset, size;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!eps_base_force_specified) {</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = getVpdPartitionFromFullBios(&offset, &size);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (VPD_OK == retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+        eps_base = offset;</span><br><span style="color: hsl(120, 100%, 40%);">+        vpd_size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (overwrite_it) {</span><br><span style="color: hsl(120, 100%, 40%);">+          retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+          fprintf(stderr, "[ERROR] getVpdPartitionFromFullBios() failed.");</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Update the following variables:</span><br><span style="color: hsl(120, 100%, 40%);">+   *   eps_base: integer, the VPD EPS address in ROM.</span><br><span style="color: hsl(120, 100%, 40%);">+   *   vpd_offset: integer, the VPD partition offset in file (read_buf[]).</span><br><span style="color: hsl(120, 100%, 40%);">+   *   vpd_buf: uint8_t*, points to the VPD partition.</span><br><span style="color: hsl(120, 100%, 40%);">+   *   eps: vpd_entry*, points to the EPS structure.</span><br><span style="color: hsl(120, 100%, 40%);">+   *   eps_offset: integer, the offset of EPS related to vpd_buf[].</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_buf = &read_buf[vpd_offset];</span><br><span style="color: hsl(120, 100%, 40%);">+  /* eps and eps_offset will be set slightly later. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (eps_base == UNKNOWN_EPS_BASE) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] Cannot determine eps_base. Cannot go on.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                    "        You may use -E to specify the value.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* In overwrite mode, we don't care the content inside. Stop parsing. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (overwrite_it) {</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (vpd_size < sizeof(struct vpd_entry)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] vpd_size:%d is too small to be compared.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            vpd_size);</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  /* try to search the EPS if it is not aligned to the begin of partition. */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (index = 0; index < vpd_size; index += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (isEps(&vpd_buf[index])) {</span><br><span style="color: hsl(120, 100%, 40%);">+      eps = (struct vpd_entry *)&vpd_buf[index];</span><br><span style="color: hsl(120, 100%, 40%);">+      eps_offset = index;</span><br><span style="color: hsl(120, 100%, 40%);">+      break;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  /* jump if the VPD partition is not recognized. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (index >= vpd_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* But OKAY if the VPD partition starts with FF, which might be un-used. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!memcmp("\xff\xff\xff\xff", vpd_buf, sizeof(VPD_ENTRY_MAGIC) - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[WARN] VPD partition not formatted. It's fine.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "SMBIOS signature is not matched.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "You may use -O to overwrite the data.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* adjust the eps_base for data->offset field below. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!eps_base_force_specified) {</span><br><span style="color: hsl(120, 100%, 40%);">+    related_eps_base = eps->table_address - sizeof(*eps);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    related_eps_base = eps_base;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* EPS is done above. Parse structure tables below. */</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Get the first type 241 blob, at the tail of EPS. */</span><br><span style="color: hsl(120, 100%, 40%);">+  header = (struct vpd_header*)(((uint8_t*)eps) + eps->entry_length);</span><br><span style="color: hsl(120, 100%, 40%);">+  data = (struct vpd_table_binary_blob_pointer *)</span><br><span style="color: hsl(120, 100%, 40%);">+         ((uint8_t *)header + sizeof(*header));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* prepare data structure to compare */</span><br><span style="color: hsl(120, 100%, 40%);">+  uuid_parse(GOOGLE_SPD_UUID, spd_uuid);</span><br><span style="color: hsl(120, 100%, 40%);">+  uuid_parse(GOOGLE_VPD_2_0_UUID, vpd_2_0_uuid);</span><br><span style="color: hsl(120, 100%, 40%);">+  uuid_parse(GOOGLE_VPD_1_2_UUID, vpd_1_2_uuid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Iterate all tables */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (expected_handle = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       header->type != VPD_TYPE_END;</span><br><span style="color: hsl(120, 100%, 40%);">+       ++expected_handle) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* make sure we haven't have too much handle already. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (expected_handle > 65535) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] too many handles. Terminate parsing.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* check type */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (header->type != VPD_TYPE_BINARY_BLOB_POINTER) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] We now only support Binary Blob Pointer (241). "</span><br><span style="color: hsl(120, 100%, 40%);">+                      "But the %dth handle is type %d. Terminate parsing.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      header->handle, header->type);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* make sure handle is increasing as expected */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (header->handle != expected_handle) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] The handle value must be %d, but is %d.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                      "        Use -O option to re-format.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      expected_handle, header->handle);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* point to the table 241 data part */</span><br><span style="color: hsl(120, 100%, 40%);">+    index = data->offset - related_eps_base;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (index >= file_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] the table offset looks suspicious. "</span><br><span style="color: hsl(120, 100%, 40%);">+                      "index=0x%x, data->offset=0x%x, related_eps_base=0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      index, data->offset, related_eps_base);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * The main switch case</span><br><span style="color: hsl(120, 100%, 40%);">+     */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!memcmp(data->uuid, spd_uuid, sizeof(data->uuid))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* SPD */</span><br><span style="color: hsl(120, 100%, 40%);">+      spd_offset = index;</span><br><span style="color: hsl(120, 100%, 40%);">+      spd_len = data->size;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (vpd_offset + spd_offset + spd_len >= file_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "[ERROR] SPD offset in BBP is not correct.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "        vpd=0x%x spd=0x%x len=0x%x file_size=0x%x\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "        If this file is VPD partition only, try to\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "        use -E to adjust offset values.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        (uint32_t)vpd_offset, (uint32_t)spd_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                        spd_len, file_size);</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!(spd_data = malloc(spd_len))) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "spd_data: malloc(%d bytes) failed.\n", spd_len);</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(spd_data, &read_buf[vpd_offset + spd_offset], spd_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      file_flag |= HAS_SPD;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (!memcmp(data->uuid, vpd_2_0_uuid, sizeof(data->uuid))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* VPD 2.0 */</span><br><span style="color: hsl(120, 100%, 40%);">+      /* iterate all pairs */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (;</span><br><span style="color: hsl(120, 100%, 40%);">+           vpd_buf[index] != VPD_TYPE_TERMINATOR &&</span><br><span style="color: hsl(120, 100%, 40%);">+           vpd_buf[index] != VPD_TYPE_IMPLICIT_TERMINATOR;) {</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = decodeToContainer(container, file_size, vpd_buf, &index);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (VPD_OK != retval)</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+          fprintf(stderr, "decodeToContainer() error.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+      file_flag |= HAS_VPD_2_0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (!memcmp(data->uuid, vpd_1_2_uuid, sizeof(data->uuid))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* VPD 1_2: please refer to "Google VPD Type 241 Format v1.2" */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct V12 {</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t prod_sn[0x20];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t sku[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t uuid[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t mb_sn[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t imei[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t ssd_sn[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t mem_sn[0x10];</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t wlan_mac[0x06];</span><br><span style="color: hsl(120, 100%, 40%);">+      } *v12 = (void*)&vpd_buf[index];</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"Product_SN",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->prod_sn, sizeof(v12->prod_sn)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"SKU",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->sku, sizeof(v12->sku)), VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"UUID",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractHex(v12->uuid, sizeof(v12->uuid)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"MotherBoard_SN",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->mb_sn, sizeof(v12->mb_sn)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"IMEI",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->imei, sizeof(v12->imei)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"SSD_SN",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->ssd_sn, sizeof(v12->ssd_sn)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"Memory_SN",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractString(v12->mem_sn, sizeof(v12->mem_sn)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      setString(container, (uint8_t*)"WLAN_MAC",</span><br><span style="color: hsl(120, 100%, 40%);">+                extractHex(v12->wlan_mac, sizeof(v12->wlan_mac)),</span><br><span style="color: hsl(120, 100%, 40%);">+                VPD_AS_LONG_AS);</span><br><span style="color: hsl(120, 100%, 40%);">+      file_flag |= HAS_VPD_1_2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* un-supported UUID */</span><br><span style="color: hsl(120, 100%, 40%);">+      char outstr[37];  /* 36-char + 1 null terminator */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      uuid_unparse(data->uuid, outstr);</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] un-supported UUID: %s\n", outstr);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* move to next table */</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((table_len = vpd_type241_size(header)) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] Cannot get type 241 structure table length.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    header = (struct vpd_header*)((uint8_t*)header + table_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    data = (struct vpd_table_binary_blob_pointer *)</span><br><span style="color: hsl(120, 100%, 40%);">+           ((uint8_t *)header + sizeof(*header));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+teardown:</span><br><span style="color: hsl(120, 100%, 40%);">+  free(read_buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+vpd_err_t saveFile(const struct PairContainer *container, const char *filename,</span><br><span style="color: hsl(120, 100%, 40%);">+             int write_back_to_flash) {</span><br><span style="color: hsl(120, 100%, 40%);">+  FILE *fp;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char eps[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+  int eps_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t file_seek;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct google_vpd_info *info = (struct google_vpd_info *)buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(eps, 0xff, sizeof(eps));</span><br><span style="color: hsl(120, 100%, 40%);">+  buf_len = sizeof(*info);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* prepare info */</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(info, 0, sizeof(*info));</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(info->header.magic, VPD_INFO_MAGIC, sizeof(info->header.magic));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* encode into buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = encodeContainer(&file, max_buf_len, buf, &buf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "encodeContainer() error.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = encodeVpdTerminator(max_buf_len, buf, &buf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "Out of space for terminator.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  info->size = buf_len - sizeof(*info);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = buildEpsAndTables(buf_len, sizeof(eps), eps, &eps_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "Cannot build EPS.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  assert(eps_len <= GOOGLE_SPD_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Write data in the following order:</span><br><span style="color: hsl(120, 100%, 40%);">+   *   1. EPS</span><br><span style="color: hsl(120, 100%, 40%);">+   *   2. SPD</span><br><span style="color: hsl(120, 100%, 40%);">+   *   3. VPD 2.0</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (found_vpd) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* We found VPD partition in -f file, which means file is existed.</span><br><span style="color: hsl(120, 100%, 40%);">+     * Instead of truncating the whole file, open to write partial. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(fp = fopen(filename, "r+"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "File [%s] cannot be opened for write.\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* VPD is not found, which means the file is pure VPD data.</span><br><span style="color: hsl(120, 100%, 40%);">+     * Always creates the new file and overwrites the original content. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(fp = fopen(filename, "w+"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "File [%s] cannot be opened for write.\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (write_back_to_flash) {</span><br><span style="color: hsl(120, 100%, 40%);">+    file_seek = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    file_seek = vpd_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* write EPS */</span><br><span style="color: hsl(120, 100%, 40%);">+  fseek(fp, file_seek + eps_offset, SEEK_SET);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (fwrite(eps, eps_len, 1, fp) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "fwrite(EPS) error (%s)\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* write SPD */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (spd_data) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fseek(fp, file_seek + spd_offset, SEEK_SET);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (fwrite(spd_data, spd_len, 1, fp) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "fwrite(SPD) error (%s)\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* write VPD 2.0 */</span><br><span style="color: hsl(120, 100%, 40%);">+  fseek(fp, file_seek + vpd_2_0_offset, SEEK_SET);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (fwrite(buf, buf_len, 1, fp) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "fwrite(VPD 2.0) error (%s)\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  fclose(fp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+teardown:</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void usage(const char *progname) {</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Chrome OS VPD 2.0 utility --\n");</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef VPD_VERSION</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("%s\n", VPD_VERSION);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Usage: %s [OPTION] ...\n", progname);</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("   OPTIONs include:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -h               This help page and version.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -f <filename>    The output file name.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -E <address>     EPS base address (default:0x240000).\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -S <key=file>    To add/change a string value, reading its\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("                       base64 contents from a file.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -s <key=value>   To add/change a string value.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -p <pad length>  Pad if length is shorter.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -i <partition>   Specify VPD partition name in fmap.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -l               List content in the file.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      --sh             Dump content for shell script.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -0/--null-terminated\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("                       Dump content in null terminate format.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -O               Overwrite and re-format VPD partition.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -g <key>         Print value string only.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -d <key>         Delete a key.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("   Notes:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      You can specify multiple -s and -d. However, vpd always\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("         applies -s first, then -d.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("      -g and -l must be mutually exclusive.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main(int argc, char *argv[]) {</span><br><span style="color: hsl(120, 100%, 40%);">+  int opt;</span><br><span style="color: hsl(120, 100%, 40%);">+  int option_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  vpd_err_t retval = VPD_OK;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *optstring = "hf:E:s:S:p:i:lOg:d:0";</span><br><span style="color: hsl(120, 100%, 40%);">+  static struct option long_options[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    {"help", 0, 0, 'h'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"file", 0, 0, 'f'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"epsbase", 0, 0, 'E'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"string", 0, 0, 's'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"base64file", 0, 0, 'S'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"pad", required_argument, 0, 'p'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"partition", 0, 0, 'i'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"list", 0, 0, 'l'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"overwrite", 0, 0, 'O'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"filter", 0, 0, 'g'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"sh", 0, &export_type, VPD_EXPORT_AS_PARAMETER},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"null-terminated", 0, 0, '0'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {"delete", 0, 0, 'd'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {0, 0, 0, 0}</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  char *filename = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *load_file = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *save_file = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *tmp_part_file = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *tmp_full_file = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *key_to_export = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  int write_back_to_flash = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int list_it = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int overwrite_it = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int modified = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  int num_to_delete;</span><br><span style="color: hsl(120, 100%, 40%);">+  int read_from_file = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&file);</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&set_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+  initContainer(&del_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  while ((opt = getopt_long(argc, argv, optstring,</span><br><span style="color: hsl(120, 100%, 40%);">+                            long_options, &option_index)) != EOF) {</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (opt) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'h':</span><br><span style="color: hsl(120, 100%, 40%);">+        usage(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'f':</span><br><span style="color: hsl(120, 100%, 40%);">+        filename = strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'E':</span><br><span style="color: hsl(120, 100%, 40%);">+        errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        eps_base = strtoul(optarg, (char **) NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        eps_base_force_specified = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* FIXME: this is not a stable way to detect error because</span><br><span style="color: hsl(120, 100%, 40%);">+         *        implementation may (or may not) assign errno. */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!eps_base && errno == EINVAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+          fprintf(stderr, "Not a number for EPS base address: %s\n", optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+          retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+          goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'S':</span><br><span style="color: hsl(120, 100%, 40%);">+        read_from_file = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Fall through into the next case */</span><br><span style="color: hsl(120, 100%, 40%);">+      case 's':</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = parseString((uint8_t*)optarg, read_from_file);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+          fprintf(stderr, "The string [%s] cannot be parsed.\n\n", optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+          goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+        read_from_file = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'p':</span><br><span style="color: hsl(120, 100%, 40%);">+        errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        pad_value_len = strtol(optarg, (char **) NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* FIXME: this is not a stable way to detect error because</span><br><span style="color: hsl(120, 100%, 40%);">+         *        implementation may (or may not) assign errno. */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!pad_value_len && errno == EINVAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+          fprintf(stderr, "Not a number for pad length: %s\n", optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+          retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+          goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'i':</span><br><span style="color: hsl(120, 100%, 40%);">+        snprintf(fmap_vpd_area_name, sizeof(fmap_vpd_area_name), "%s", optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'l':</span><br><span style="color: hsl(120, 100%, 40%);">+        list_it = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'O':</span><br><span style="color: hsl(120, 100%, 40%);">+        overwrite_it = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        modified = 1;  /* This option forces to write empty data back even</span><br><span style="color: hsl(120, 100%, 40%);">+                        * no new pair is given. */</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'g':</span><br><span style="color: hsl(120, 100%, 40%);">+        key_to_export = (uint8_t*)strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 'd':</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Add key into container for delete. Since value is non-sense,</span><br><span style="color: hsl(120, 100%, 40%);">+         * keep it empty. */</span><br><span style="color: hsl(120, 100%, 40%);">+        setString(&del_argument, (const uint8_t *)optarg,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 (const uint8_t *)"", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case '0':</span><br><span style="color: hsl(120, 100%, 40%);">+        export_type = VPD_EXPORT_NULL_TERMINATE;</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "Invalid option (%s), use --help for usage.\n", optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+        break;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (optind < argc) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] unexpected argument: %s\n\n", argv[optind]);</span><br><span style="color: hsl(120, 100%, 40%);">+    usage(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  tmp_part_file = myMkTemp();</span><br><span style="color: hsl(120, 100%, 40%);">+  tmp_full_file = myMkTemp();</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!tmp_part_file || !tmp_full_file) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] Failed creating temporary files.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYSTEM;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (list_it && key_to_export) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] -l and -g must be mutually exclusive.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_EXPORT_KEY_VALUE != export_type && !list_it) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr,</span><br><span style="color: hsl(120, 100%, 40%);">+            "[ERROR] --sh/--null-terminated can be set only if -l is set.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_SYNTAX;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* to avoid malicious attack, we replace suspicious chars. */</span><br><span style="color: hsl(120, 100%, 40%);">+  fmapNormalizeAreaName(fmap_vpd_area_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* if no filename is specified, call flashrom to read from flash. */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!filename) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (FLASHROM_OK != flashromPartialRead(tmp_part_file, tmp_full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           fmap_vpd_area_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[WARN] flashromPartialRead() failed, try full read.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Try to read whole file */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (FLASHROM_OK != flashromFullRead(tmp_full_file)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "[ERROR] flashromFullRead() error!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = VPD_ERR_ROM_READ;</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Success! Then the fmap_vpd_area_name is changed for later use. */</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    write_back_to_flash = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    load_file = tmp_full_file;</span><br><span style="color: hsl(120, 100%, 40%);">+    save_file = tmp_part_file;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+    load_file = filename;</span><br><span style="color: hsl(120, 100%, 40%);">+    save_file = filename;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  retval = loadFile(load_file, &file, overwrite_it);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "loadFile('%s') error.\n", load_file);</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Do -s */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (lenOfContainer(&set_argument) > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    mergeContainer(&file, &set_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+    modified++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Do -d */</span><br><span style="color: hsl(120, 100%, 40%);">+  num_to_delete = lenOfContainer(&del_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (subtractContainer(&file, &del_argument) !=</span><br><span style="color: hsl(120, 100%, 40%);">+      num_to_delete) {</span><br><span style="color: hsl(120, 100%, 40%);">+    fprintf(stderr, "[ERROR] At least one of the keys to delete"</span><br><span style="color: hsl(120, 100%, 40%);">+        " does not exist. Command ignored.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = VPD_ERR_PARAM;</span><br><span style="color: hsl(120, 100%, 40%);">+    goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (num_to_delete > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    modified++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Do -g */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (key_to_export) {</span><br><span style="color: hsl(120, 100%, 40%);">+    struct StringPair* foundString = findString(&file, key_to_export, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (NULL == foundString) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "findString(): Vpd data '%s' was not found.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                key_to_export);</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t dump_buf[BUF_LEN * 2];</span><br><span style="color: hsl(120, 100%, 40%);">+      int dump_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = exportStringValue(foundString,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 sizeof(dump_buf), dump_buf, &dump_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "exportStringValue(): Cannot export the value.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      fwrite(dump_buf, dump_len, 1, stdout);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Do -l */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (list_it) {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Reserve larger size because the exporting generates longer string than</span><br><span style="color: hsl(120, 100%, 40%);">+     * the encoded data. */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t list_buf[BUF_LEN * 5 + 64];</span><br><span style="color: hsl(120, 100%, 40%);">+    int list_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = exportContainer(export_type, &file, sizeof(list_buf),</span><br><span style="color: hsl(120, 100%, 40%);">+                             list_buf, &list_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "exportContainer(): Cannot generate string.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Export necessary program parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_EXPORT_AS_PARAMETER == export_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("%s%s -i %s \\\n",</span><br><span style="color: hsl(120, 100%, 40%);">+             SH_COMMENT, argv[0], fmap_vpd_area_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (filename)</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("    -f %s \\\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    fwrite(list_buf, list_len, 1, stdout);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (modified) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (file_flag & HAS_VPD_1_2) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "[ERROR] Writing VPD 1.2 not supported yet.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      retval = VPD_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    retval = saveFile(&file, save_file, write_back_to_flash);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (VPD_OK != retval) {</span><br><span style="color: hsl(120, 100%, 40%);">+      fprintf(stderr, "saveFile('%s') error: %d\n", filename, retval);</span><br><span style="color: hsl(120, 100%, 40%);">+      goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (write_back_to_flash) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (FLASHROM_OK != flashromPartialWrite(save_file, tmp_full_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              fmap_vpd_area_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "flashromPartialWrite() error.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        retval = VPD_ERR_ROM_WRITE;</span><br><span style="color: hsl(120, 100%, 40%);">+        goto teardown;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+teardown:</span><br><span style="color: hsl(120, 100%, 40%);">+  if (spd_data) free(spd_data);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (filename) free(filename);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (key_to_export) free(key_to_export);</span><br><span style="color: hsl(120, 100%, 40%);">+  destroyContainer(&file);</span><br><span style="color: hsl(120, 100%, 40%);">+  destroyContainer(&set_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+  destroyContainer(&del_argument);</span><br><span style="color: hsl(120, 100%, 40%);">+  cleanTempFiles();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return retval;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25615">change 25615</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25615"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ib3b8de7d27236f3f0e216d5517da0c1f00682f52 </div>
<div style="display:none"> Gerrit-Change-Number: 25615 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Marcello Sylvester Bauer </div>