summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2019-02-28 20:05:27 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-04-05 09:21:44 -0700
commit1d6c7bb9773f76aa70ce65822fa001ff72892cd2 (patch)
tree3631462d9540df08d13cffa9a7f8e7e9bb3e7899 /test
parent63bf8f8ba87b23378391b147f1b3e9fdcf3d8dc5 (diff)
downloadchrome-ec-1d6c7bb9773f76aa70ce65822fa001ff72892cd2.tar.gz
nvmem: test modifications to support the new scheme
This patch includes changes to support testing of the new nvmem implementation. Making fizz compatible required duplicating a lot of functionality available in the test/ directory (fuzz/nvmem_tpm2_mock.c is very similar to test/nvmem_tpm2_mock.c), but I could not find an easy way to avoid it. BRANCH=cr50, cr50-mp BUG=b:69907320, b:129710256 CQ-DEPEND=CL:1496607 TEST=with the rest of the patches applied 'make buildall -j' succeeds, which confirms both test and fuzz success. Change-Id: Ife999b04d22f8ddbe9ea5d35f4c3e21f57592754 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1450278 Reviewed-by: Andrey Pronin <apronin@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/build.mk9
-rw-r--r--test/legacy_nvmem_dump.h1043
-rw-r--r--test/nvmem.c1655
-rw-r--r--test/nvmem_test.h28
-rw-r--r--test/nvmem_tpm2_mock.c377
-rw-r--r--test/nvmem_vars.c538
-rw-r--r--test/nvmem_vars.tasklist17
-rw-r--r--test/pinweaver.c84
-rw-r--r--test/test_config.h64
9 files changed, 2673 insertions, 1142 deletions
diff --git a/test/build.mk b/test/build.mk
index 979fc352fe..6900c97e3d 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -47,7 +47,6 @@ test-list-host += motion_angle_tablet
test-list-host += motion_lid
test-list-host += mutex
test-list-host += nvmem
-test-list-host += nvmem_vars
test-list-host += pingpong
test-list-host += pinweaver
test-list-host += power_button
@@ -105,8 +104,7 @@ motion_angle-y=motion_angle.o motion_angle_data_literals.o motion_common.o
motion_angle_tablet-y=motion_angle_tablet.o motion_angle_data_literals_tablet.o motion_common.o
motion_lid-y=motion_lid.o
mutex-y=mutex.o
-nvmem-y=nvmem.o
-nvmem_vars-y=nvmem_vars.o
+nvmem-y=nvmem.o nvmem_tpm2_mock.o
pingpong-y=pingpong.o
pinweaver-y=pinweaver.o
power_button-y=power_button.o
@@ -135,3 +133,8 @@ vboot-y=vboot.o
float-y=fp.o
fp-y=fp.o
x25519-y=x25519.o
+
+TPM2_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
+$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT)
+$(out)/RO/test/nvmem.o: CFLAGS += -I$(TPM2_ROOT)
+$(out)/RO/test/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_ROOT)
diff --git a/test/legacy_nvmem_dump.h b/test/legacy_nvmem_dump.h
new file mode 100644
index 0000000000..6816673c23
--- /dev/null
+++ b/test/legacy_nvmem_dump.h
@@ -0,0 +1,1043 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * This is a test NVMEM snapshot, it includes a couple of key,value pairs and
+ * a set of TPM reserved and evictable objects, as created after the first
+ * Chrome OS boot on a device.
+ *
+ * This binary dump is placed in a separate file not to free up the test file
+ * using it.
+ */
+ 0x00, 0x65, 0x8e, 0x10, 0x80, 0xca, 0x52, 0x1e, 0x95, 0x81, 0x12, 0x4f,
+ 0x36, 0x78, 0x9a, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x63, 0x72, 0x6f, 0x73, 0x2d, 0x70,
+ 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00, 0xe1, 0xac, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x37, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xbd, 0xfe, 0xff, 0xff, 0x85, 0xfc, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0xde, 0x01, 0x00, 0xb4, 0xde, 0x01, 0x00,
+ 0x9b, 0x0f, 0x06, 0x00, 0xbc, 0xde, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x5b, 0x15, 0xa1, 0x0a, 0x05, 0x12, 0x58, 0x84, 0xbf, 0xf6, 0xc9, 0xf3,
+ 0xdd, 0xb7, 0x26, 0xce, 0x56, 0x9e, 0x5f, 0x7a, 0xa8, 0xd4, 0x8a, 0x67,
+ 0x5c, 0x26, 0x35, 0x0e, 0xb2, 0x13, 0x2c, 0x79, 0x20, 0x00, 0x26, 0xca,
+ 0x7d, 0xb8, 0x1a, 0x1f, 0x0b, 0x5c, 0x0a, 0xf3, 0xb5, 0xe2, 0x6a, 0xec,
+ 0x1a, 0x0d, 0x90, 0x8b, 0x92, 0x3c, 0x07, 0xb0, 0x41, 0xb0, 0x27, 0x20,
+ 0x88, 0x33, 0xfe, 0x5c, 0xf2, 0x7b, 0x20, 0x00, 0x9e, 0xb7, 0xa2, 0x4c,
+ 0xad, 0x6c, 0xc0, 0x92, 0x92, 0xef, 0xbc, 0x56, 0x65, 0x47, 0xf9, 0x09,
+ 0xd1, 0xc4, 0xbc, 0x36, 0xe8, 0x3a, 0xc2, 0x8a, 0x11, 0x3a, 0xca, 0xe1,
+ 0x66, 0xd7, 0x85, 0x57, 0x20, 0x00, 0x0c, 0x6d, 0xc7, 0x61, 0x92, 0xfc,
+ 0x1b, 0x24, 0x02, 0xc1, 0x92, 0x0e, 0xf4, 0xa1, 0x75, 0xbe, 0xb1, 0x3d,
+ 0x29, 0xfe, 0x1e, 0xe2, 0x65, 0xf5, 0x25, 0xae, 0xaf, 0xfe, 0x73, 0x32,
+ 0x35, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x52, 0x01, 0x7b, 0x53, 0xc5, 0x95, 0xa0, 0x3a, 0x07, 0xd5, 0x62, 0x7f,
+ 0xd3, 0x9c, 0x85, 0xaa, 0xfc, 0x56, 0xa0, 0xfa, 0x3a, 0xe8, 0x17, 0x38,
+ 0xc3, 0x59, 0x65, 0xbe, 0x75, 0x1b, 0xdc, 0xdc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x84, 0xe7, 0x7e, 0x46, 0xfe, 0xbd,
+ 0x10, 0xdd, 0x5b, 0x09, 0xb2, 0xe2, 0xb1, 0x3f, 0xbf, 0x9a, 0xf3, 0xd7,
+ 0xfb, 0xf7, 0x28, 0xbb, 0x24, 0x10, 0xa3, 0xf3, 0x18, 0xa4, 0xa2, 0x16,
+ 0xd5, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0xff, 0xff, 0xff, 0x0b, 0x00,
+ 0x03, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x03, 0xff, 0xff, 0xff, 0x0d, 0x00,
+ 0x03, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
+ 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ /* Manually added nonempty pcr. Array 0, index 0 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ /* Manually added nonempty pcr. Array 1, index 1 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* Manually added ram index of size 0x20 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x69, 0x17, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
+ 0xc0, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x20, 0x04, 0x62, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xef, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x01, 0x30, 0x82, 0x03, 0xeb, 0x30, 0x82, 0x02, 0xd3, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x10, 0x71, 0x7b, 0xc1, 0xfb, 0x3b, 0x21, 0xb5,
+ 0xfb, 0x02, 0x21, 0x1f, 0xb7, 0x0a, 0xbc, 0xe4, 0x88, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
+ 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69,
+ 0x61, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b,
+ 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
+ 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1b, 0x45, 0x6e,
+ 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e,
+ 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17,
+ 0x43, 0x52, 0x4f, 0x53, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x50, 0x52, 0x44,
+ 0x20, 0x45, 0x4b, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x20, 0x43, 0x41, 0x30,
+ 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x37, 0x30, 0x36, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x37, 0x30, 0x36,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x5a, 0x30, 0x00, 0x30, 0x82, 0x01,
+ 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01,
+ 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf8, 0x26, 0xde, 0x99, 0xfa, 0x25,
+ 0xe1, 0xb6, 0xda, 0xb7, 0x88, 0x74, 0x77, 0x3d, 0x9a, 0x2e, 0xd0, 0xbd,
+ 0xda, 0x68, 0x8b, 0x1b, 0x8c, 0xe7, 0xd1, 0x0b, 0xf4, 0xfe, 0x8e, 0x94,
+ 0x09, 0x43, 0x11, 0x11, 0x46, 0xfc, 0x16, 0xb5, 0x15, 0x67, 0xab, 0x1b,
+ 0x8f, 0x25, 0xa7, 0x28, 0x04, 0xcc, 0xed, 0xf0, 0x5c, 0xbe, 0xa3, 0xfd,
+ 0x85, 0x85, 0x9b, 0xea, 0x6c, 0x61, 0x8b, 0x7e, 0xd2, 0x76, 0x2b, 0x37,
+ 0x87, 0x30, 0xd3, 0x9f, 0x0d, 0xb7, 0x0e, 0x31, 0x39, 0x3b, 0x3a, 0xa3,
+ 0xab, 0xb5, 0x21, 0x15, 0xb2, 0xc6, 0x7e, 0x78, 0xdc, 0x97, 0x53, 0x56,
+ 0x3f, 0xe9, 0xb4, 0x4e, 0xb8, 0xdd, 0x09, 0xa6, 0x37, 0xd3, 0xf7, 0x11,
+ 0xa2, 0x52, 0x50, 0xa6, 0x53, 0x44, 0xce, 0xb3, 0x9c, 0x02, 0xd8, 0x59,
+ 0x04, 0x3b, 0xba, 0x6c, 0xce, 0xf1, 0x6b, 0x33, 0x60, 0x14, 0x6b, 0xa0,
+ 0x3d, 0x2e, 0x66, 0x67, 0x82, 0x4f, 0x13, 0xa1, 0x82, 0xc4, 0x15, 0x08,
+ 0x7e, 0x59, 0xba, 0x84, 0x3e, 0xac, 0x12, 0x42, 0x98, 0x3d, 0x6e, 0xda,
+ 0xa9, 0xc3, 0xd7, 0x45, 0xeb, 0xc8, 0xec, 0x2a, 0x94, 0x9e, 0xc1, 0xf7,
+ 0x71, 0xca, 0x3d, 0xb3, 0xd2, 0x68, 0x2a, 0xc0, 0xbe, 0x9e, 0x2f, 0x26,
+ 0xf3, 0xf9, 0xb9, 0x7f, 0x21, 0x7f, 0x2f, 0x8b, 0x1b, 0x10, 0xb1, 0x09,
+ 0xc8, 0xab, 0xae, 0xda, 0xae, 0x66, 0x07, 0x4a, 0xc0, 0x75, 0x2a, 0x29,
+ 0x74, 0xb2, 0x99, 0xa6, 0x58, 0x84, 0xdc, 0x3e, 0x6b, 0x47, 0x37, 0xcb,
+ 0xb1, 0xc8, 0xcc, 0x81, 0xb3, 0x8b, 0x3a, 0x0c, 0xd4, 0x6a, 0x11, 0x3f,
+ 0x25, 0x17, 0x5d, 0xaf, 0x33, 0x8a, 0x32, 0x9d, 0x93, 0xef, 0xdb, 0x95,
+ 0x60, 0x5a, 0x15, 0xc5, 0x20, 0x7a, 0xec, 0xce, 0xa9, 0x31, 0x70, 0x24,
+ 0xd1, 0x4d, 0x29, 0xed, 0xeb, 0xec, 0xac, 0x53, 0x19, 0xc3, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xdf, 0x30, 0x81, 0xdc, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x00,
+ 0x20, 0x30, 0x51, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, 0xff, 0x04,
+ 0x47, 0x30, 0x45, 0xa4, 0x43, 0x30, 0x41, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x05, 0x67, 0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, 0x3a, 0x34,
+ 0x37, 0x34, 0x46, 0x34, 0x46, 0x34, 0x37, 0x31, 0x0f, 0x30, 0x0d, 0x06,
+ 0x05, 0x67, 0x81, 0x05, 0x02, 0x02, 0x0c, 0x04, 0x48, 0x31, 0x42, 0x32,
+ 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, 0x81, 0x05, 0x02, 0x03, 0x0c,
+ 0x0b, 0x69, 0x64, 0x3a, 0x30, 0x30, 0x31, 0x33, 0x30, 0x30, 0x33, 0x37,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02,
+ 0x30, 0x00, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x0c, 0x30,
+ 0x0a, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x02, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0x15, 0x39, 0x34, 0xfc, 0x59, 0x19, 0xcd, 0x29, 0x82, 0xf1, 0xf4, 0x7f,
+ 0xad, 0x85, 0xd6, 0x44, 0x69, 0xa1, 0xa1, 0x7b, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, 0x07, 0x06, 0x05, 0x67, 0x81, 0x05,
+ 0x08, 0x01, 0x30, 0x21, 0x06, 0x03, 0x55, 0x1d, 0x09, 0x04, 0x1a, 0x30,
+ 0x18, 0x30, 0x16, 0x06, 0x05, 0x67, 0x81, 0x05, 0x02, 0x10, 0x31, 0x0d,
+ 0x30, 0x0b, 0x0c, 0x03, 0x32, 0x2e, 0x30, 0x02, 0x01, 0x00, 0x02, 0x01,
+ 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x00, 0x1a, 0xef,
+ 0x74, 0x00, 0x05, 0xa3, 0x1c, 0x8c, 0xec, 0x0b, 0x6d, 0x67, 0x1b, 0x26,
+ 0x34, 0x62, 0xb3, 0x0c, 0x04, 0x34, 0xf6, 0x8c, 0x60, 0xa3, 0xcc, 0x5a,
+ 0xa7, 0x5f, 0x30, 0xa1, 0x50, 0x13, 0xb5, 0xf2, 0x83, 0x49, 0xfb, 0x35,
+ 0x01, 0x74, 0xde, 0xba, 0x3d, 0xba, 0x81, 0x0c, 0x87, 0x92, 0xbb, 0x20,
+ 0xc8, 0xe3, 0x4e, 0x15, 0xd4, 0x6d, 0xe6, 0x6f, 0xae, 0xca, 0x29, 0xa2,
+ 0xba, 0x5a, 0xac, 0xb9, 0x0c, 0xef, 0x85, 0xce, 0x6c, 0x03, 0xbd, 0x57,
+ 0x41, 0x90, 0x13, 0x68, 0x7b, 0xe0, 0x5e, 0xc6, 0x96, 0xe6, 0xbd, 0x67,
+ 0x62, 0x83, 0x7b, 0xc1, 0xa6, 0xfc, 0x2e, 0xc7, 0x74, 0x54, 0xef, 0x93,
+ 0x28, 0x8b, 0x1f, 0x73, 0x3c, 0xa9, 0x11, 0x6e, 0xac, 0xdf, 0x9e, 0xe2,
+ 0xb5, 0x6d, 0x62, 0x44, 0xc3, 0xa0, 0xf6, 0x82, 0x7b, 0x23, 0x82, 0x73,
+ 0x91, 0x22, 0x11, 0x7b, 0xb8, 0x8a, 0x19, 0x45, 0x2b, 0x99, 0xdc, 0x7a,
+ 0xa1, 0x21, 0xd8, 0x37, 0x51, 0x60, 0xfb, 0x20, 0xab, 0x2d, 0x6c, 0x32,
+ 0x07, 0xb8, 0x15, 0xed, 0x7c, 0x62, 0xe9, 0xc9, 0x1d, 0x50, 0x6c, 0x6c,
+ 0x1b, 0x55, 0xcd, 0x92, 0xb6, 0xc1, 0x9a, 0x3d, 0xac, 0x01, 0xc0, 0x66,
+ 0xca, 0xc1, 0x91, 0x09, 0x50, 0x4d, 0x1a, 0xc0, 0x6f, 0xe3, 0x2d, 0x4b,
+ 0x7f, 0xee, 0xa9, 0xff, 0xeb, 0x0d, 0x5d, 0xe5, 0x64, 0xfd, 0x52, 0x6e,
+ 0x8a, 0x91, 0x2d, 0xd0, 0x13, 0xf5, 0xcd, 0x32, 0xfb, 0xe2, 0xe7, 0x6d,
+ 0xfb, 0x05, 0x6a, 0x2a, 0xec, 0xc8, 0xa6, 0xd3, 0x94, 0xee, 0x89, 0x40,
+ 0x24, 0x39, 0x84, 0x6a, 0xc1, 0xd4, 0x16, 0xdf, 0x0f, 0x79, 0x3b, 0x57,
+ 0x17, 0x4d, 0x2d, 0x58, 0x65, 0x19, 0xce, 0x0c, 0xf4, 0x86, 0x19, 0xa6,
+ 0xfe, 0xd7, 0xac, 0x7c, 0x15, 0x7d, 0x06, 0x08, 0xd2, 0xb6, 0xb9, 0x5e,
+ 0x00, 0x29, 0x1b, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x01, 0x00, 0xc0,
+ 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x20, 0x04, 0x62, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x01, 0x30, 0x82, 0x03, 0x20, 0x30, 0x82, 0x02, 0x08, 0xa0, 0x03, 0x02,
+ 0x01, 0x02, 0x02, 0x10, 0x64, 0x2e, 0x3d, 0x44, 0xaa, 0x6d, 0x90, 0x95,
+ 0x42, 0x28, 0x7d, 0x07, 0x5e, 0xe7, 0x68, 0x66, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
+ 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61,
+ 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x47,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x24,
+ 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1b, 0x45, 0x6e, 0x67,
+ 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74,
+ 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x17, 0x43,
+ 0x52, 0x4f, 0x53, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x50, 0x52, 0x44, 0x20,
+ 0x45, 0x4b, 0x20, 0x52, 0x4f, 0x4f, 0x54, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x38, 0x30, 0x37, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x37, 0x30, 0x36, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x32, 0x5a, 0x30, 0x00, 0x30, 0x59, 0x30, 0x13,
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xad,
+ 0x72, 0x36, 0x6c, 0x76, 0x5e, 0x69, 0xa1, 0xf5, 0xeb, 0xbf, 0x5d, 0x38,
+ 0x1d, 0x76, 0xda, 0xb3, 0x80, 0xf6, 0xa8, 0xf3, 0x2c, 0x42, 0x7e, 0xc8,
+ 0xd7, 0xc9, 0x46, 0xbd, 0xc6, 0x80, 0x7f, 0xd3, 0xf4, 0xac, 0xa5, 0x60,
+ 0xa3, 0xf1, 0x31, 0x6c, 0xdf, 0x87, 0x95, 0x5c, 0xb6, 0xf3, 0x79, 0xff,
+ 0x7b, 0x46, 0x53, 0xec, 0x3f, 0x20, 0xde, 0x59, 0xa5, 0x2d, 0xcb, 0x77,
+ 0x55, 0x89, 0xad, 0xa3, 0x81, 0xdf, 0x30, 0x81, 0xdc, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x00,
+ 0x20, 0x30, 0x51, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, 0xff, 0x04,
+ 0x47, 0x30, 0x45, 0xa4, 0x43, 0x30, 0x41, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x05, 0x67, 0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, 0x3a, 0x34,
+ 0x37, 0x34, 0x46, 0x34, 0x46, 0x34, 0x37, 0x31, 0x0f, 0x30, 0x0d, 0x06,
+ 0x05, 0x67, 0x81, 0x05, 0x02, 0x02, 0x0c, 0x04, 0x48, 0x31, 0x42, 0x32,
+ 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, 0x81, 0x05, 0x02, 0x03, 0x0c,
+ 0x0b, 0x69, 0x64, 0x3a, 0x30, 0x30, 0x31, 0x33, 0x30, 0x30, 0x33, 0x37,
+ 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02,
+ 0x30, 0x00, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x0c, 0x30,
+ 0x0a, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, 0x02, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0x15, 0x39, 0x34, 0xfc, 0x59, 0x19, 0xcd, 0x29, 0x82, 0xf1, 0xf4, 0x7f,
+ 0xad, 0x85, 0xd6, 0x44, 0x69, 0xa1, 0xa1, 0x7b, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, 0x07, 0x06, 0x05, 0x67, 0x81, 0x05,
+ 0x08, 0x01, 0x30, 0x21, 0x06, 0x03, 0x55, 0x1d, 0x09, 0x04, 0x1a, 0x30,
+ 0x18, 0x30, 0x16, 0x06, 0x05, 0x67, 0x81, 0x05, 0x02, 0x10, 0x31, 0x0d,
+ 0x30, 0x0b, 0x0c, 0x03, 0x32, 0x2e, 0x30, 0x02, 0x01, 0x00, 0x02, 0x01,
+ 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3a, 0xe0, 0x1e,
+ 0x15, 0xd7, 0x11, 0x97, 0xc6, 0xc3, 0x50, 0x9a, 0x0b, 0x7f, 0x0a, 0x5e,
+ 0x7d, 0xd2, 0xb8, 0x08, 0xc0, 0x98, 0x35, 0x73, 0x6d, 0x85, 0x19, 0x46,
+ 0x76, 0x27, 0xcb, 0xa3, 0x66, 0x7f, 0xc9, 0x26, 0x20, 0x52, 0xb5, 0xe9,
+ 0xf5, 0xa0, 0x7a, 0x1d, 0xb3, 0x78, 0x66, 0x6d, 0x13, 0xcb, 0x82, 0x5b,
+ 0x09, 0xdc, 0xcb, 0x01, 0x0c, 0x3e, 0x34, 0x4a, 0x92, 0x44, 0x30, 0x44,
+ 0xda, 0x49, 0xad, 0x45, 0x17, 0xc3, 0x5b, 0x80, 0x8c, 0xa5, 0x11, 0xc4,
+ 0x07, 0x1a, 0x06, 0x43, 0x9c, 0x57, 0x51, 0x42, 0x35, 0xfd, 0xec, 0x68,
+ 0xe3, 0xe8, 0x3f, 0x5b, 0xb0, 0x01, 0x4f, 0xcb, 0xe0, 0x2a, 0x7f, 0xe6,
+ 0x89, 0xcc, 0xef, 0x59, 0xbb, 0x11, 0xed, 0xcb, 0xe6, 0xc9, 0x55, 0x94,
+ 0xf0, 0x5b, 0xee, 0x33, 0xc9, 0xed, 0x1b, 0x02, 0xeb, 0x90, 0x33, 0x0e,
+ 0xc1, 0x8f, 0x1c, 0x37, 0x3f, 0x9c, 0x59, 0x96, 0xe7, 0x73, 0xb1, 0x90,
+ 0x7a, 0x93, 0x2f, 0x4e, 0x98, 0xff, 0xff, 0xa7, 0xfb, 0x7f, 0xb9, 0x1b,
+ 0x46, 0xb8, 0x64, 0x12, 0x92, 0x74, 0x54, 0xe1, 0x7f, 0x07, 0xfa, 0xc4,
+ 0x2e, 0x53, 0xa8, 0x6a, 0xe5, 0x23, 0x92, 0x9e, 0x39, 0x37, 0xfc, 0x5d,
+ 0x2f, 0x7b, 0x69, 0x84, 0xd3, 0x69, 0x4e, 0xd1, 0x98, 0xda, 0x53, 0x34,
+ 0x80, 0xe6, 0xeb, 0xd5, 0x9a, 0x10, 0x5d, 0xc9, 0x88, 0x2b, 0x13, 0x9c,
+ 0xb9, 0xad, 0x15, 0x4f, 0x3a, 0x6c, 0x0d, 0xd4, 0x50, 0x0b, 0x1d, 0xfb,
+ 0x36, 0x74, 0xf2, 0x3e, 0x32, 0xce, 0x69, 0x5f, 0x67, 0x63, 0x33, 0x0f,
+ 0x7b, 0xc9, 0x5e, 0x68, 0x39, 0xdf, 0xb9, 0xe2, 0x73, 0xd5, 0xd5, 0x40,
+ 0xd8, 0x62, 0x0a, 0x4e, 0x45, 0x6f, 0xc1, 0x92, 0x9c, 0x41, 0x58, 0x21,
+ 0xd4, 0x60, 0x0b, 0xc4, 0x7c, 0x9c, 0xe8, 0x57, 0x5c, 0xed, 0xbc, 0xc1,
+ 0xf4, 0x51, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc3, 0x3c, 0x43,
+ 0xf2, 0xe7, 0x82, 0xf3, 0x5c, 0xec, 0x61, 0x96, 0xef, 0xf5, 0xfb, 0x24,
+ 0x87, 0xaa, 0xf9, 0x5f, 0x3f, 0xf6, 0x5e, 0xdd, 0x0a, 0x59, 0x33, 0xbb,
+ 0xe1, 0xaf, 0x3b, 0xb2, 0x26, 0xfa, 0x1b, 0x00, 0x00, 0x08, 0x10, 0x00,
+ 0x01, 0x08, 0x10, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05,
+ 0x60, 0x00, 0x00, 0x00, 0xe0, 0xd7, 0xdd, 0x01, 0x00, 0xe3, 0xad, 0x05,
+ 0x00, 0xe2, 0xad, 0x05, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x53, 0x07,
+ 0x00, 0x00, 0x53, 0x07, 0x00, 0x30, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xd7, 0xdd, 0x01, 0x00, 0xd3, 0x3a, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xb0, 0xde, 0x01, 0x00, 0xb4, 0xde, 0x01, 0x00, 0x9b, 0x0f, 0x06,
+ 0x00, 0xbc, 0xde, 0x01, 0x00, 0x40, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0xb5, 0x01, 0x00, 0xd7, 0xdd, 0x01,
+ 0x00, 0x1f, 0xbd, 0x05, 0x00, 0x4e, 0xbd, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x01, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x19, 0x53, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x4c, 0x57, 0x52, 0x47, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xa0, 0x1c, 0x00, 0x00, 0x07, 0x10,
+ 0x00, 0x01, 0x07, 0x10, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x4c,
+ 0x05, 0x60, 0x20, 0x00, 0x09, 0x93, 0x3c, 0xce, 0xeb, 0xb4, 0x41, 0x11,
+ 0x18, 0x81, 0x1d, 0xd4, 0x47, 0x78, 0x80, 0x08, 0x88, 0x86, 0x62, 0x2d,
+ 0xd7, 0x79, 0x94, 0x46, 0x62, 0x26, 0x68, 0x8e, 0xee, 0xe6, 0x6a, 0xa1,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb0, 0xde, 0x01, 0x00, 0xb4, 0xde, 0x01, 0x00, 0x9b, 0x0f,
+ 0x06, 0x00, 0xbc, 0xde, 0x01, 0x00, 0x40, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0xb5, 0x01, 0x00, 0xd7, 0xdd,
+ 0x01, 0x00, 0x1f, 0xbd, 0x05, 0x00, 0x4e, 0xbd, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x01, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x19, 0x53, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x4f, 0x64, 0x1d, 0x00, 0x00, 0x05, 0x00, 0x80, 0x01,
+ 0x05, 0x00, 0x80, 0x01, 0x0b, 0x00, 0x01, 0x00, 0x04, 0x28, 0x04, 0xb0,
+ 0x00, 0x00, 0x40, 0x00, 0xcd, 0xd4, 0x97, 0x24, 0x1f, 0x26, 0xd9, 0x91,
+ 0xad, 0xb8, 0xd2, 0xcb, 0x46, 0x14, 0x65, 0x72, 0x91, 0x8d, 0x56, 0x2e,
+ 0x7b, 0x3f, 0x74, 0x89, 0x80, 0xc6, 0x18, 0xbf, 0xea, 0x58, 0xe6, 0xf6,
+ 0x54, 0xde, 0x01, 0x00, 0xaa, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb0, 0xde, 0x01, 0x00, 0xb4, 0xde, 0x01, 0x00, 0x9b, 0x0f, 0x06, 0x00,
+ 0xbc, 0xde, 0x01, 0x00, 0x40, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xfe, 0x1b, 0x00, 0x00, 0x05, 0x00, 0x80, 0x01, 0x43, 0xcf, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0xf0, 0xde, 0x01, 0x00, 0x69, 0x01, 0x00, 0x00, 0xb3, 0xd3, 0x05, 0x00,
+ 0xa4, 0xde, 0x01, 0x00, 0xa8, 0xde, 0x01, 0x00, 0xf4, 0xde, 0x01, 0x00,
+ 0xd1, 0x73, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xde, 0x40, 0x00,
+ 0x78, 0x04, 0x01, 0x00, 0x32, 0x4d, 0x50, 0x54, 0x01, 0x00, 0x00, 0x00,
+ 0xe0, 0xa7, 0x0d, 0x1e, 0x0d, 0xe2, 0x5a, 0xb8, 0xd4, 0x5e, 0xb8, 0x2b,
+ 0xcc, 0x99, 0xd2, 0x6a, 0x8f, 0xf0, 0x52, 0x18, 0x72, 0x02, 0x16, 0x8e,
+ 0x83, 0x06, 0xba, 0x01, 0xe4, 0xcc, 0xbf, 0xcf, 0x80, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x81, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b,
+ 0x00, 0x03, 0x04, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x00, 0x43,
+ 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9b, 0x0f,
+ 0x10, 0x85, 0x8c, 0x80, 0xfc, 0x15, 0x23, 0xeb, 0x29, 0x04, 0x2d, 0x2c,
+ 0xfc, 0xed, 0xc4, 0x1e, 0x3f, 0xf3, 0xc2, 0x3f, 0x42, 0xd0, 0x5c, 0x8d,
+ 0xe7, 0x3f, 0xc3, 0x17, 0x6d, 0xc5, 0x2c, 0xa8, 0x5f, 0x29, 0x80, 0x82,
+ 0xf2, 0x1f, 0xd1, 0x48, 0xfc, 0x50, 0x96, 0x51, 0x13, 0x5f, 0xbf, 0xa0,
+ 0xdf, 0xb0, 0x16, 0xe2, 0x80, 0x54, 0x11, 0x10, 0x7d, 0x05, 0xf6, 0x16,
+ 0x07, 0xd3, 0xbe, 0x8e, 0x16, 0x6c, 0x83, 0x56, 0xdc, 0xd9, 0x0d, 0x29,
+ 0x42, 0x26, 0x37, 0xa0, 0x5a, 0xa0, 0x47, 0x02, 0x80, 0xfd, 0x2c, 0x8c,
+ 0x23, 0x6c, 0x96, 0x44, 0x9f, 0xd6, 0x7e, 0x33, 0x70, 0xd0, 0xe7, 0x3c,
+ 0x93, 0xf6, 0x4c, 0xf3, 0xf9, 0x6f, 0x5d, 0x40, 0xa0, 0xb0, 0xf5, 0x69,
+ 0xcc, 0x60, 0x19, 0x83, 0x0b, 0xe1, 0xc6, 0xc7, 0x8b, 0xa1, 0x3a, 0x01,
+ 0x16, 0x68, 0xd6, 0x28, 0xf9, 0x19, 0xee, 0x2b, 0x74, 0x9a, 0xba, 0xac,
+ 0x5e, 0x4e, 0x8d, 0x1d, 0x86, 0xef, 0xaf, 0xa4, 0xb4, 0xbd, 0xd4, 0x97,
+ 0x08, 0x6f, 0x20, 0x9b, 0xb3, 0xe8, 0x5e, 0x43, 0x9e, 0xad, 0x05, 0xf8,
+ 0xf0, 0x18, 0x53, 0xaf, 0xda, 0xb7, 0xbc, 0xe1, 0x43, 0xda, 0x03, 0xc0,
+ 0xe4, 0x5a, 0xd1, 0x74, 0xc4, 0x63, 0x2c, 0x22, 0x64, 0x34, 0x61, 0x07,
+ 0x26, 0x3d, 0x8c, 0x91, 0x29, 0xcc, 0x22, 0x5f, 0x14, 0xe9, 0xef, 0x7e,
+ 0xbb, 0x80, 0xf3, 0xed, 0x35, 0xbb, 0xf9, 0xca, 0xa5, 0x53, 0xff, 0x47,
+ 0x9d, 0xc7, 0xf4, 0x1e, 0xfe, 0x24, 0xf1, 0xbd, 0x30, 0x3e, 0x4c, 0xd6,
+ 0x47, 0x2c, 0x00, 0x16, 0x78, 0x61, 0xc4, 0x72, 0xb1, 0x39, 0xe1, 0x5d,
+ 0x18, 0x10, 0xa4, 0x1c, 0x4e, 0x42, 0x27, 0xe4, 0xd2, 0x4b, 0xcb, 0x65,
+ 0x2f, 0x33, 0x69, 0x49, 0xca, 0x2a, 0x89, 0xc7, 0x5d, 0xca, 0x7e, 0xfd,
+ 0xf2, 0x6b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x73, 0x9a, 0x3e, 0x61,
+ 0x92, 0x20, 0x63, 0x87, 0x6e, 0x99, 0xaa, 0x85, 0x7b, 0x24, 0x5e, 0xee,
+ 0xfe, 0x80, 0x4d, 0xaa, 0x66, 0x1e, 0x2b, 0xe6, 0x69, 0xca, 0x1f, 0xfd,
+ 0x41, 0xe8, 0x0e, 0xca, 0x00, 0x80, 0xc5, 0xdf, 0xa6, 0x9d, 0x5a, 0x23,
+ 0xde, 0xc4, 0x38, 0xfe, 0xd0, 0x80, 0x5e, 0x7d, 0xd3, 0x01, 0x07, 0xa3,
+ 0x93, 0x80, 0x19, 0xb8, 0xf4, 0xaa, 0xb1, 0xf4, 0x09, 0x78, 0x91, 0x52,
+ 0x48, 0xb1, 0x2b, 0x1b, 0xab, 0xcc, 0x60, 0x53, 0x20, 0x92, 0x85, 0xc6,
+ 0xf7, 0xff, 0x08, 0xee, 0x68, 0x6c, 0xfd, 0x3e, 0xd6, 0x9d, 0xda, 0x0d,
+ 0x03, 0x0c, 0x7c, 0xe0, 0x2b, 0x5c, 0xd4, 0x35, 0x9b, 0x3d, 0x7d, 0xd4,
+ 0x07, 0x7c, 0x8a, 0xc3, 0x79, 0xc0, 0x4b, 0x52, 0x20, 0x18, 0x2f, 0xfe,
+ 0x19, 0xe6, 0x41, 0xac, 0x31, 0xef, 0x32, 0x8e, 0x47, 0xdf, 0x0b, 0x8d,
+ 0x6b, 0x50, 0xbe, 0x15, 0xa2, 0x17, 0x51, 0xef, 0x5e, 0x87, 0xc3, 0x2e,
+ 0xd8, 0xf8, 0xb7, 0x72, 0xc9, 0x5d, 0xe8, 0x71, 0xef, 0x32, 0x02, 0x5d,
+ 0xc5, 0x49, 0x4e, 0xb7, 0xb8, 0xdc, 0xe3, 0x9d, 0xcb, 0x29, 0x49, 0x90,
+ 0xcf, 0xdf, 0x00, 0x00, 0x00, 0x22, 0x00, 0x0b, 0x96, 0xce, 0xc6, 0x42,
+ 0x3b, 0x6f, 0x58, 0x90, 0xd2, 0x2a, 0xbc, 0xc4, 0x59, 0xa1, 0xfb, 0x63,
+ 0xc4, 0xef, 0x59, 0x2a, 0x2d, 0x92, 0x76, 0xfa, 0xdb, 0xac, 0xf6, 0x7b,
+ 0x77, 0xb7, 0x56, 0x93, 0x81, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x0b,
+ 0x68, 0x0f, 0x54, 0x0a, 0x3f, 0x27, 0xdc, 0x66, 0x76, 0x1a, 0x35, 0x71,
+ 0xe2, 0x5c, 0x08, 0xcf, 0xac, 0x39, 0xea, 0xcc, 0x01, 0x54, 0x4e, 0x48,
+ 0xaa, 0xe1, 0x5c, 0xa5, 0xb7, 0xe1, 0x5b, 0x50, 0x7c, 0x20, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x81, 0x38, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x0b,
+ 0x00, 0x03, 0x04, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x00, 0x43,
+ 0x00, 0x10, 0x00, 0x03, 0x00, 0x10, 0x00, 0x20, 0x6c, 0x05, 0x79, 0x5e,
+ 0x36, 0x4a, 0x04, 0x2c, 0x10, 0x8e, 0x50, 0xcc, 0x60, 0x7e, 0x18, 0xa1,
+ 0xe5, 0x4a, 0x96, 0x56, 0xf1, 0x5f, 0x34, 0x95, 0x36, 0xea, 0x00, 0x64,
+ 0xb9, 0xf4, 0x49, 0x91, 0x00, 0x20, 0x7f, 0x8c, 0xad, 0xea, 0x97, 0xba,
+ 0x99, 0x28, 0x93, 0xb4, 0xcc, 0xa7, 0x36, 0xfa, 0x61, 0xd8, 0x78, 0xb6,
+ 0x06, 0xcd, 0xe3, 0x27, 0x99, 0x7b, 0xaa, 0x3e, 0xa9, 0x4e, 0xf2, 0x93,
+ 0x18, 0x06, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x16, 0xba, 0x08, 0xd2,
+ 0xd8, 0x63, 0x38, 0xba, 0xb9, 0x0b, 0xce, 0x5b, 0x72, 0x9a, 0x88, 0x08,
+ 0x25, 0xb9, 0xbd, 0xab, 0x16, 0x77, 0x43, 0xbb, 0xcd, 0x3d, 0x4d, 0x48,
+ 0xbc, 0x77, 0xf8, 0xd3, 0x00, 0x20, 0x0f, 0xd6, 0x89, 0x31, 0xdc, 0xfa,
+ 0x70, 0x00, 0x6a, 0x4b, 0x59, 0x60, 0x28, 0x01, 0x54, 0x39, 0x4e, 0xa1,
+ 0x97, 0x28, 0xe0, 0x84, 0x92, 0x0e, 0x35, 0xdc, 0xb3, 0x9a, 0x11, 0x08,
+ 0x7c, 0x93, 0x00, 0x00, 0x00, 0x22, 0x00, 0x0b, 0x5d, 0xab, 0xa0, 0x5d,
+ 0x70, 0x5f, 0x6e, 0x78, 0xeb, 0x82, 0x8c, 0xb4, 0x77, 0x45, 0x95, 0x50,
+ 0x6b, 0x7c, 0x97, 0x5d, 0x2d, 0x31, 0x76, 0x0e, 0x81, 0x9e, 0x4b, 0xa3,
+ 0x80, 0xf5, 0xff, 0x86, 0x81, 0x00, 0x00, 0x01, 0x00, 0x22, 0x00, 0x0b,
+ 0x85, 0xf4, 0xbe, 0x91, 0xe1, 0x2b, 0x4c, 0x2d, 0xaa, 0x64, 0xb1, 0x90,
+ 0x5f, 0xec, 0x74, 0xea, 0xec, 0x2c, 0x3d, 0x0d, 0xbb, 0x26, 0xc0, 0x49,
+ 0x3d, 0xae, 0xa0, 0xe4, 0x72, 0xfa, 0xba, 0x15, 0x74, 0x22, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b,
+ 0x00, 0x02, 0x04, 0x72, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xed, 0x72, 0x50, 0x56, 0x10, 0xb7,
+ 0xab, 0x52, 0x50, 0x32, 0x4f, 0x82, 0x87, 0x94, 0x83, 0x84, 0x55, 0xeb,
+ 0xda, 0x78, 0x46, 0x34, 0x48, 0xc4, 0xc6, 0x28, 0x47, 0xf4, 0x4c, 0xfd,
+ 0x1f, 0x04, 0xcd, 0xb9, 0x72, 0x6a, 0x49, 0x6c, 0x1c, 0x9b, 0x07, 0x5b,
+ 0xe8, 0xef, 0xaf, 0x0b, 0xeb, 0xb1, 0xcb, 0x24, 0x0e, 0x63, 0x2f, 0x35,
+ 0x3c, 0x79, 0x0c, 0xde, 0xf5, 0xdb, 0x06, 0xe9, 0x68, 0xf4, 0xf0, 0x8e,
+ 0xf1, 0xbf, 0x98, 0x9a, 0xd9, 0x2b, 0x45, 0x85, 0x83, 0xda, 0xd9, 0xf3,
+ 0x6f, 0x1a, 0x24, 0xe8, 0x5d, 0xad, 0xda, 0xa7, 0xfc, 0x03, 0x67, 0xb0,
+ 0xdf, 0x07, 0xbd, 0xe1, 0x1e, 0x7d, 0xa1, 0xea, 0x59, 0xfb, 0xb9, 0x48,
+ 0x2d, 0x45, 0x0c, 0x1b, 0x52, 0x0e, 0xb3, 0xe6, 0xac, 0x4a, 0x91, 0x1c,
+ 0xb1, 0x2f, 0xee, 0xae, 0xf4, 0x0a, 0x79, 0x81, 0x92, 0xab, 0xaa, 0xff,
+ 0x44, 0x0f, 0x8d, 0xe7, 0x30, 0xfd, 0xee, 0x62, 0x0f, 0x92, 0x4d, 0x08,
+ 0xe7, 0xd0, 0xdb, 0x16, 0xf2, 0x27, 0x73, 0x59, 0x18, 0xc5, 0xd9, 0x0d,
+ 0xac, 0xaf, 0xc0, 0xd0, 0xdc, 0xfd, 0x1d, 0xeb, 0x74, 0x33, 0x59, 0xd6,
+ 0x30, 0xe1, 0x29, 0x81, 0xa5, 0xeb, 0x67, 0xc6, 0x32, 0x98, 0x37, 0x12,
+ 0xe8, 0x12, 0x3c, 0x5b, 0xd1, 0xc7, 0x9e, 0x9d, 0x5b, 0xe3, 0x7d, 0x5c,
+ 0xf6, 0x9e, 0x4d, 0xdf, 0x65, 0xe1, 0x95, 0x14, 0xf6, 0xda, 0x94, 0x91,
+ 0x76, 0x91, 0x6b, 0x39, 0x37, 0xf0, 0x72, 0xf9, 0x7f, 0xc1, 0x09, 0x9d,
+ 0x33, 0xf5, 0x26, 0x84, 0xe2, 0xa2, 0x94, 0xc3, 0xad, 0x4a, 0xc2, 0x86,
+ 0xa0, 0x1a, 0xf2, 0x0e, 0xa1, 0x98, 0xb1, 0x9f, 0x50, 0x54, 0xd5, 0xc8,
+ 0x58, 0x11, 0xc3, 0x76, 0x63, 0xc0, 0x49, 0x7b, 0xa5, 0x80, 0x79, 0x75,
+ 0xc0, 0x0c, 0xe9, 0x8a, 0xb0, 0xbe, 0x09, 0x54, 0xfa, 0x19, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfa, 0x82, 0xd6, 0x21, 0xf1, 0x41,
+ 0x7e, 0xca, 0x35, 0x00, 0x73, 0x63, 0x3f, 0x8d, 0x38, 0xbd, 0x4d, 0xd0,
+ 0x27, 0x0d, 0xe2, 0x66, 0xa5, 0x3c, 0x47, 0x14, 0xe7, 0x36, 0x38, 0x87,
+ 0xe2, 0x5d, 0x6d, 0x2a, 0x19, 0x10, 0xee, 0xfe, 0xf1, 0x6d, 0x6d, 0xb5,
+ 0x2c, 0x2f, 0xe3, 0x8f, 0x9b, 0x5f, 0x73, 0x8b, 0xdd, 0x1b, 0x0d, 0xe8,
+ 0x81, 0x53, 0x79, 0x9b, 0xca, 0x86, 0x03, 0xf9, 0x2d, 0x6e, 0x85, 0x26,
+ 0x14, 0xa7, 0x71, 0xd5, 0xf8, 0xd8, 0x30, 0x27, 0x26, 0x08, 0x30, 0x17,
+ 0xf8, 0xc2, 0x17, 0x6a, 0xb3, 0x7e, 0x98, 0x69, 0x19, 0x94, 0x51, 0x34,
+ 0x94, 0x3c, 0xcf, 0x45, 0x9a, 0x9d, 0x9d, 0xea, 0xcf, 0x04, 0x74, 0x74,
+ 0x79, 0x09, 0x3f, 0xa0, 0xaa, 0x25, 0xd2, 0xda, 0x1f, 0x1a, 0xc6, 0x87,
+ 0xcf, 0x17, 0x1c, 0xfc, 0x1d, 0x59, 0x4e, 0x6d, 0x2f, 0x32, 0x28, 0x39,
+ 0xb0, 0xcd, 0x00, 0x00, 0x00, 0x22, 0x00, 0x0b, 0x92, 0x80, 0x9c, 0x28,
+ 0xa0, 0xc7, 0x75, 0x91, 0x80, 0xc9, 0x86, 0x63, 0xe1, 0xa7, 0x19, 0x33,
+ 0x21, 0xd8, 0x47, 0x8c, 0xac, 0xd4, 0x51, 0x7d, 0x78, 0x31, 0x84, 0x74,
+ 0x49, 0x63, 0x40, 0xba, 0x81, 0x00, 0x00, 0x02, 0x00, 0x22, 0x00, 0x0b,
+ 0xe9, 0x80, 0x8e, 0x73, 0x7d, 0xaa, 0xc3, 0xf8, 0x84, 0xaf, 0x7d, 0x18,
+ 0x10, 0x7c, 0xed, 0xf3, 0x14, 0x72, 0x61, 0x97, 0xb6, 0xd7, 0xbb, 0x3a,
+ 0x47, 0xb0, 0x91, 0xb0, 0xba, 0x7c, 0xbc, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x20, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x12, 0x00, 0x76, 0x61, 0x72, 0x31, 0x74, 0x68, 0x69, 0x73, 0x5f,
+ 0x69, 0x73, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f,
+ 0x31, 0x04, 0x12, 0x00, 0x76, 0x61, 0x72, 0x32, 0x74, 0x68, 0x69, 0x73,
+ 0x5f, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65,
+ 0x5f, 0x32, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
diff --git a/test/nvmem.c b/test/nvmem.c
index 99b2d554e9..2b814251c9 100644
--- a/test/nvmem.c
+++ b/test/nvmem.c
@@ -5,11 +5,15 @@
* Test Cr-50 Non-Voltatile memory module
*/
+#include "nvmem_test.h"
+
#include "common.h"
#include "console.h"
#include "crc.h"
-#include "nvmem.h"
#include "flash.h"
+#include "new_nvmem.h"
+#include "nvmem.h"
+#include "printf.h"
#include "shared_mem.h"
#include "task.h"
#include "test_util.h"
@@ -19,16 +23,29 @@
#define WRITE_SEGMENT_LEN 200
#define WRITE_READ_SEGMENTS 4
-uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {
- NVMEM_USER_0_SIZE,
- NVMEM_USER_1_SIZE,
- NVMEM_USER_2_SIZE
+enum test_failure_mode failure_mode;
+
+static const uint8_t legacy_nvmem_image[] = {
+#include "legacy_nvmem_dump.h"
};
+BUILD_ASSERT(sizeof(legacy_nvmem_image) == NVMEM_PARTITION_SIZE);
+
static uint8_t write_buffer[NVMEM_PARTITION_SIZE];
-static uint8_t read_buffer[NVMEM_PARTITION_SIZE];
static int flash_write_fail;
-static int lock_test_started;
+
+struct nvmem_test_result {
+ int var_count;
+ int reserved_obj_count;
+ int evictable_obj_count;
+ int deleted_obj_count;
+ int delimiter_count;
+ int unexpected_count;
+ size_t valid_data_size;
+ size_t erased_data_size;
+};
+
+static struct nvmem_test_result test_result;
int app_cipher(const void *salt_p, void *out_p, const void *in_p, size_t size)
{
@@ -50,15 +67,28 @@ void app_compute_hash(uint8_t *p_buf, size_t num_bytes,
uint32_t crc;
uint32_t *p_data;
int n;
+ size_t tail_size;
crc32_init();
- /* Assuming here that buffer is 4 byte aligned and that num_bytes is
- * divisible by 4
- */
+ /* Assuming here that buffer is 4 byte aligned. */
p_data = (uint32_t *)p_buf;
- for (n = 0; n < num_bytes/4; n++)
+ for (n = 0; n < num_bytes / 4; n++)
crc32_hash32(*p_data++);
- crc = crc32_result();
+
+ tail_size = num_bytes % 4;
+ if (tail_size) {
+ uint32_t tail;
+
+ tail = 0;
+ memcpy(&tail, p_data, tail_size);
+ crc32_hash32(tail);
+ }
+
+ /*
+ * Crc32 of 0xffffffff is 0xffffffff. Let's spike the results to avoid
+ * this unfortunate Crc32 property.
+ */
+ crc = crc32_result() ^ 0x55555555;
for (n = 0; n < hash_bytes; n += sizeof(crc)) {
size_t copy_bytes = MIN(sizeof(crc), hash_bytes - n);
@@ -73,652 +103,1263 @@ int flash_pre_op(void)
return flash_write_fail ? EC_ERROR_UNKNOWN : EC_SUCCESS;
}
-static int generate_random_data(int offset, int num_bytes)
+static void dump_nvmem_state(const char *title,
+ const struct nvmem_test_result *tr)
+{
+ ccprintf("\n%s:\n", title);
+ ccprintf("var_count: %d\n", tr->var_count);
+ ccprintf("reserved_obj_count: %d\n", tr->reserved_obj_count);
+ ccprintf("evictable_obj_count: %d\n", tr->evictable_obj_count);
+ ccprintf("deleted_obj_count: %d\n", tr->deleted_obj_count);
+ ccprintf("deimiter_count: %d\n", tr->delimiter_count);
+ ccprintf("unexpected_count: %d\n", tr->unexpected_count);
+ ccprintf("valid_data_size: %d\n", tr->valid_data_size);
+ ccprintf("erased_data_size: %d\n\n", tr->erased_data_size);
+}
+
+static void wipe_out_nvmem_cache(void)
+{
+ memset(nvmem_cache_base(NVMEM_TPM), 0, nvmem_user_sizes[NVMEM_TPM]);
+}
+
+static int prepare_nvmem_contents(void)
+{
+ struct nvmem_tag *tag;
+
+ memcpy(write_buffer, legacy_nvmem_image, sizeof(write_buffer));
+ tag = (struct nvmem_tag *)write_buffer;
+
+ app_compute_hash(tag->padding, NVMEM_PARTITION_SIZE - NVMEM_SHA_SIZE,
+ tag->sha, sizeof(tag->sha));
+ app_cipher(tag->sha, tag + 1, tag + 1,
+ NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag));
+
+ return flash_physical_write(CONFIG_FLASH_NVMEM_BASE_A -
+ CONFIG_PROGRAM_MEMORY_BASE,
+ sizeof(write_buffer), write_buffer);
+}
+
+static int iterate_over_flash(void)
{
- int m, n, limit;
- uint32_t r_data;
+ enum ec_error_list rv;
+ struct nn_container *ch;
+ struct access_tracker at = {};
+ uint8_t buf[CONFIG_FLASH_BANK_SIZE];
+
+ memset(&test_result, 0, sizeof(test_result));
+ ch = (struct nn_container *)buf;
+
+ while ((rv = get_next_object(&at, ch, 1)) == EC_SUCCESS)
+ switch (ch->container_type) {
+ case NN_OBJ_OLD_COPY:
+ if (ch->container_type_copy == NN_OBJ_TRANSACTION_DEL) {
+ test_result.delimiter_count++;
+ } else {
+ test_result.deleted_obj_count++;
+ test_result.erased_data_size += ch->size;
+ }
+ break;
+
+ case NN_OBJ_TUPLE:
+ test_result.var_count++;
+ test_result.valid_data_size += ch->size;
+ break;
+
+ case NN_OBJ_TPM_RESERVED:
+ test_result.reserved_obj_count++;
+ test_result.valid_data_size += ch->size;
+ break;
+
+ case NN_OBJ_TPM_EVICTABLE:
+ test_result.evictable_obj_count++;
+ test_result.valid_data_size += ch->size;
+ break;
+
+ case NN_OBJ_TRANSACTION_DEL:
+ test_result.delimiter_count++;
+ break;
+ default:
+ test_result.unexpected_count++;
+ break;
+ }
- /* Ensure it will fit in the write buffer */
- TEST_ASSERT((num_bytes + offset) <= NVMEM_PARTITION_SIZE);
- /* Seed random number sequence */
- r_data = prng((uint32_t)clock());
- m = 0;
- while (m < num_bytes) {
- r_data = prng(r_data);
- limit = MIN(4, num_bytes - m);
- /* No byte alignment assumptions */
- for (n = 0; n < limit; n++)
- write_buffer[offset + m + n] = (r_data >> (n*8)) & 0xff;
- m += limit;
+ if (rv != EC_ERROR_MEMORY_ALLOCATION) {
+ ccprintf("\n%s:%d - unexpected return value %d\n", __func__,
+ __LINE__, rv);
+ return rv;
}
- return EC_SUCCESS;
+ /* Verify that there is a delimiter at the top of the flash. */
+ if (at.mt.data_offset > sizeof(*at.mt.ph)) {
+ if ((at.mt.ph == at.dt.ph) &&
+ (((at.mt.data_offset - sizeof(struct nn_container))) ==
+ at.dt.data_offset)) {
+ return EC_SUCCESS;
+ }
+ } else {
+ if ((at.dt.ph == list_element_to_ph(at.list_index)) &&
+ (at.dt.data_offset ==
+ (CONFIG_FLASH_BANK_SIZE - sizeof(struct nn_container)))) {
+ ccprintf("%s:%d edge delimiter case OK\n", __func__,
+ __LINE__);
+ return EC_SUCCESS;
+ }
+ }
+ ccprintf("%s:%d bad delimiter location: ph %p, "
+ "dt.ph %p, offset %d, delim offset %d\n",
+ __func__, __LINE__, at.mt.ph, at.dt.ph, at.mt.data_offset,
+ at.dt.data_offset);
+
+ return EC_ERROR_INVAL;
}
-static int test_write_read(uint32_t offset, uint32_t num_bytes, int user)
+static void *page_to_flash_addr(int page_num)
{
- int ret;
+ uint32_t base_offset = CONFIG_FLASH_NEW_NVMEM_BASE_A;
- /* Generate source data */
- generate_random_data(0, num_bytes);
- /* Write source data to NvMem */
- ret = nvmem_write(offset, num_bytes, write_buffer, user);
- /* Write to flash */
- ret = nvmem_commit();
- if (ret != EC_SUCCESS)
- return ret;
- /* Read from flash */
- nvmem_read(offset, num_bytes, read_buffer, user);
- /* Verify that write to flash was successful */
- TEST_ASSERT_ARRAY_EQ(write_buffer, read_buffer, num_bytes);
+ if (page_num > NEW_NVMEM_TOTAL_PAGES)
+ return NULL;
- return EC_SUCCESS;
+ if (page_num >= (NEW_NVMEM_TOTAL_PAGES / 2)) {
+ page_num -= (NEW_NVMEM_TOTAL_PAGES / 2);
+ base_offset = CONFIG_FLASH_NEW_NVMEM_BASE_B;
+ }
+
+ return (void *)((uintptr_t)base_offset +
+ page_num * CONFIG_FLASH_BANK_SIZE);
}
-static int write_full_buffer(uint32_t size, int user)
+static int post_init_from_scratch(uint8_t flash_value)
{
- uint32_t offset;
- uint32_t len;
- int ret;
+ int i;
+ void *flash_p;
+
+ memset(write_buffer, flash_value, sizeof(write_buffer));
+
+ /* Overwrite nvmem flash space with junk value. */
+ flash_physical_write(
+ CONFIG_FLASH_NEW_NVMEM_BASE_A - CONFIG_PROGRAM_MEMORY_BASE,
+ NEW_FLASH_HALF_NVMEM_SIZE, (const char *)write_buffer);
+ flash_physical_write(
+ CONFIG_FLASH_NEW_NVMEM_BASE_B - CONFIG_PROGRAM_MEMORY_BASE,
+ NEW_FLASH_HALF_NVMEM_SIZE, (const char *)write_buffer);
+
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(test_result.var_count == 0);
+ TEST_ASSERT(test_result.reserved_obj_count == 38);
+ TEST_ASSERT(test_result.evictable_obj_count == 0);
+ TEST_ASSERT(test_result.deleted_obj_count == 0);
+ TEST_ASSERT(test_result.unexpected_count == 0);
+ TEST_ASSERT(test_result.valid_data_size == 1088);
+ TEST_ASSERT(total_var_space == 0);
+
+ for (i = 0; i < (NEW_NVMEM_TOTAL_PAGES - 1); i++) {
+ flash_p = page_to_flash_addr(i);
+
+ TEST_ASSERT(!!flash_p);
+ TEST_ASSERT(is_uninitialized(flash_p, CONFIG_FLASH_BANK_SIZE));
+ }
- /* Start at beginning of the user buffer */
- offset = 0;
- do {
- /* User default segment length unless it will exceed */
- len = MIN(WRITE_SEGMENT_LEN, size - offset);
- /* Generate data for tx buffer */
- generate_random_data(offset, len);
- /* Write data to Nvmem cache memory */
- nvmem_write(offset, len, &write_buffer[offset], user);
- /* Write to flash */
- ret = nvmem_commit();
- if (ret != EC_SUCCESS)
- return ret;
- /* Adjust starting offset by segment length */
- offset += len;
- } while (offset < size);
-
- /* Entire flash buffer should be full at this point */
- nvmem_read(0, size, read_buffer, user);
- /* Verify that write to flash was successful */
- TEST_ASSERT_ARRAY_EQ(write_buffer, read_buffer, size);
+ flash_p = page_to_flash_addr(i);
+ TEST_ASSERT(!is_uninitialized(flash_p, CONFIG_FLASH_BANK_SIZE));
return EC_SUCCESS;
}
+/*
+ * The purpose of this test is to check NvMem initialization when NvMem is
+ * completely erased (i.e. following SpiFlash write of program). In this case,
+ * nvmem_init() is expected to create initial flash storage containing
+ * reserved objects only.
+ */
static int test_fully_erased_nvmem(void)
{
- /*
- * The purpose of this test is to check NvMem intialization when NvMem
- * is completely erased (i.e. following SpiFlash write of program). In
- * this configuration, nvmem_init() should be able to detect this case
- * and configure an initial NvMem partition.
- */
- /* Erase full NvMem area */
- flash_physical_erase(CONFIG_FLASH_NVMEM_OFFSET_A,
- NVMEM_PARTITION_SIZE);
- flash_physical_erase(CONFIG_FLASH_NVMEM_OFFSET_B,
- NVMEM_PARTITION_SIZE);
- /* Call NvMem initialization function */
- return nvmem_init();
+ return post_init_from_scratch(0xff);
}
-static int test_configured_nvmem(void)
+/*
+ * The purpose of this test is to check nvmem_init() in the case when no valid
+ * pages exist but flash space is garbled as opposed to be fully erased. In
+ * this case, the initialization is expected to create one new valid page and
+ * erase the rest of the pages.
+ */
+static int test_corrupt_nvmem(void)
{
- /*
- * The purpose of this test is to check nvmem_init() when both
- * partitions are configured and valid.
- */
+ return post_init_from_scratch(0x55);
+}
- /* Call NvMem initialization */
- return nvmem_init();
+static int prepare_new_flash(void)
+{
+ TEST_ASSERT(test_fully_erased_nvmem() == EC_SUCCESS);
+
+ /* Now copy sensible information into the nvmem cache. */
+ memcpy(nvmem_cache_base(NVMEM_TPM),
+ legacy_nvmem_image + sizeof(struct nvmem_tag),
+ nvmem_user_sizes[NVMEM_TPM]);
+
+ dump_nvmem_state("after first save", &test_result);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+
+ TEST_ASSERT(test_result.deleted_obj_count == 24);
+ TEST_ASSERT(test_result.var_count == 0);
+ TEST_ASSERT(test_result.reserved_obj_count == 40);
+ TEST_ASSERT(test_result.evictable_obj_count == 9);
+ TEST_ASSERT(test_result.unexpected_count == 0);
+ TEST_ASSERT(test_result.valid_data_size == 5128);
+ TEST_ASSERT(test_result.erased_data_size == 698);
+
+ return EC_SUCCESS;
}
-/* Verify that nvmem_erase_user_data only erases the given user's data. */
-static int test_nvmem_erase_user_data(void)
+static int test_nvmem_save(void)
{
- uint32_t write_value;
- uint32_t read_value;
- int i;
+ const char *key = "var1";
+ const char *value = "value of var 1";
+ size_t total_var_size;
+ struct nvmem_test_result old_result;
- nvmem_init();
-
- /* Make sure all partitions have data in them. */
- for (i = 0; i < NVMEM_NUM_PARTITIONS; i++) {
- write_value = i;
- nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_0);
- write_value = 2;
- nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_1);
- write_value = 3;
- nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_2);
- nvmem_commit();
- }
+ TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
- /* Check that the writes took place. */
- read_value = ~write_value;
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0);
- TEST_ASSERT(read_value == i-1);
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_1);
- TEST_ASSERT(read_value == 2);
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_2);
- TEST_ASSERT(read_value == 3);
+ /*
+ * Verify that saving without changing the cache does not affect flash
+ * contents.
+ */
+ old_result = test_result;
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
/*
- * nvmem_erase_user_data() is supposed to erase the user's data across
- * all partitions.
+ * Save of unmodified cache does not modify the flash contents and
+ * does not set the delimiter.
*/
- nvmem_erase_user_data(NVMEM_USER_0);
- for (i = 0; i < NVMEM_NUM_PARTITIONS; i++) {
- /* Make sure USER 0's data is (still) gone. */
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0);
- TEST_ASSERT(read_value == 0xffffffff);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
- /* Make sure the other users' data has been untouched. */
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_1);
- TEST_ASSERT(read_value == 2);
+ wipe_out_nvmem_cache();
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
- /*
- * The active partition changes when the contents of the cache
- * changes. Therefore, in order to examine all the paritions,
- * we'll keep modifying one of the user's data.
- */
- nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_2);
- TEST_ASSERT(read_value == (3+i));
- write_value = 4 + i;
- nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_2);
- nvmem_commit();
- }
+ /*
+ * Total size test variable storage takes in flash (container header
+ * size not included).
+ */
+ total_var_size = strlen(key) + strlen(value) + sizeof(struct tuple);
+
+ /* Verify that we can add a variable to nvmem. */
+ TEST_ASSERT(setvar(key, strlen(key), value, strlen(value)) ==
+ EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+
+ /* Remove changes caused by the new var addition. */
+ test_result.var_count -= 1;
+ test_result.delimiter_count -= 1;
+ test_result.valid_data_size -= total_var_size;
+
+ TEST_ASSERT(memcmp(&test_result, &old_result, sizeof(test_result)) ==
+ 0);
+
+ /* Verify that we can delete a variable from nvmem. */
+ TEST_ASSERT(setvar(key, strlen(key), NULL, 0) == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ test_result.deleted_obj_count -= 1;
+ test_result.erased_data_size -= total_var_size;
+ test_result.delimiter_count -= 1;
+ TEST_ASSERT(memcmp(&test_result, &old_result, sizeof(test_result)) ==
+ 0);
return EC_SUCCESS;
}
-static int test_corrupt_nvmem(void)
+static size_t get_free_nvmem_room(void)
{
- uint8_t invalid_value = 0x55;
- int ret;
- struct nvmem_tag *p_part;
- uint8_t *p_data;
+ size_t free_room;
+ size_t free_pages;
+ /* Compaction kicks in when 3 pages or less are left. */
+ const size_t max_pages = NEW_NVMEM_TOTAL_PAGES - 3;
+
+ ccprintf("list index %d, data offset 0x%x\n", master_at.list_index,
+ master_at.mt.data_offset);
+
+ if (master_at.list_index >= max_pages)
+ return 0;
+
+ free_pages = max_pages - master_at.list_index;
+ free_room = (free_pages - 1) * (CONFIG_FLASH_BANK_SIZE -
+ sizeof(struct nn_page_header)) +
+ CONFIG_FLASH_BANK_SIZE - master_at.mt.data_offset;
+ ccprintf("free pages %d, data offset 0x%x\n", free_pages,
+ master_at.mt.data_offset);
+ return free_room;
+}
+
+static int test_nvmem_compaction(void)
+{
+ char value[100]; /* Definitely more than enough. */
+ const char *key = "var 1";
+ int i;
+ size_t key_len;
+ size_t val_len;
+ size_t free_room;
+ size_t real_var_size;
+ size_t var_space;
+ int max_vars;
+ int erased_data_size;
+ const size_t alignment_mask = CONFIG_FLASH_WRITE_SIZE - 1;
+
+ key_len = strlen(key);
+ val_len = snprintf(value, sizeof(value), "variable value is %04d", 0);
+
+ TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
/*
- * The purpose of this test is to check nvmem_init() in the case when no
- * vailid partition exists (not fully erased and no valid sha). In this
- * case, the initialization create one new valid partition.
+ * Remember how much room was erased before flooding nvmem with erased
+ * values.
*/
+ erased_data_size = test_result.erased_data_size;
- /* Overwrite each partition will all 0s */
- memset(write_buffer, invalid_value, NVMEM_PARTITION_SIZE);
- flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET_A,
- NVMEM_PARTITION_SIZE,
- (const char *)write_buffer);
- flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET_B,
- NVMEM_PARTITION_SIZE,
- (const char *)write_buffer);
+ /* Let's see how much free room there is. */
+ free_room = get_free_nvmem_room();
+ TEST_ASSERT(free_room);
+
+ /* How much room (key, value) pair takes in a container. */
+ real_var_size = val_len + key_len + sizeof(struct tuple);
/*
- * The initialization function will look for a valid partition and if
- * none is found, it will create one, and save it at partition index
- * 1.
+ * See how many vars including containers should be able to fit there.
+ *
+ * First calculate rounded up space a var will take. Apart from the
+ * var itself there will be a container header and a delimiter.
*/
- ret = nvmem_init();
- if (ret)
- return ret;
+ var_space = (real_var_size + 2 * sizeof(struct nn_container) +
+ alignment_mask) & ~alignment_mask;
+
+ max_vars = free_room / var_space;
/*
- * nvmem_init() called on uninitialized flash will create the first
- * valid partition with generation set to 0 at flash partition 1.
- *
- * Check here that partition 1 has a generation number of 0.
+ * And now flood the NVMEM with erased values (each new setvar()
+ * invocation erases the previous instance.
*/
- p_part = (struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_B;
- TEST_ASSERT(p_part->generation == 0);
- p_data = (uint8_t *)p_part + sizeof(struct nvmem_tag);
+ for (i = 0; i <= max_vars; i++) {
+ snprintf(value, sizeof(value), "variable value is %04d", i);
+ TEST_ASSERT(setvar(key, key_len, value, val_len) == EC_SUCCESS);
+ }
- /* Verify that partition 0 is still empty. */
- memset(write_buffer, invalid_value, NVMEM_PARTITION_SIZE);
- p_data = (void *)CONFIG_FLASH_NVMEM_BASE_A;
- TEST_ASSERT_ARRAY_EQ(write_buffer, p_data, NVMEM_PARTITION_SIZE);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ /* Make sure there was no compaction yet. */
+ TEST_ASSERT(test_result.erased_data_size > erased_data_size);
- /* Now let's write a different value into user NVMEM_CR50 */
- invalid_value ^= ~0;
- TEST_ASSERT(nvmem_write(0, sizeof(invalid_value),
- &invalid_value, NVMEM_USER_0) == EC_SUCCESS);
- TEST_ASSERT(nvmem_commit() == EC_SUCCESS);
+ /* This is how much the erased space grew as a result of flooding. */
+ erased_data_size = test_result.erased_data_size - erased_data_size;
+ TEST_ASSERT(erased_data_size == max_vars * real_var_size);
- /* Verify that partition 1 generation did not change. */
- TEST_ASSERT(p_part->generation == 0);
+ /* This will take it over the compaction limit. */
+ val_len = snprintf(value, sizeof(value), "variable value is %03d", i);
+ TEST_ASSERT(setvar(key, key_len, value, val_len) == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(test_result.erased_data_size < var_space);
+ return EC_SUCCESS;
+}
+
+static int test_configured_nvmem(void)
+{
/*
- * Now verify that partition 0 generation is set to 1;
+ * The purpose of this test is to check how nvmem_init() initializes
+ * from previously saved flash contents.
*/
- p_part = (struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_A;
- TEST_ASSERT(p_part->generation == 1);
+ TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
- return EC_SUCCESS;
+ /*
+ * This is initialization from legacy flash contents which replaces
+ * legacy flash image with the new format flash image
+ */
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* And this is initialization from the new flash layout. */
+ return nvmem_init();
}
-static int test_write_read_sequence(void)
+static uint8_t find_lb(const void *data)
{
- uint32_t offset;
- uint32_t length;
- int user;
- int n;
- int ret;
-
- for (user = 0; user < NVMEM_NUM_USERS; user++) {
- /* Length for each write/read segment */
- length = nvmem_user_sizes[user] / WRITE_READ_SEGMENTS;
- /* Start at beginning of user buffer */
- offset = 0;
- for (n = 0; n < WRITE_READ_SEGMENTS; n++) {
- ret = test_write_read(offset, length, user);
- if (ret != EC_SUCCESS)
- return ret;
- /* Adjust offset by segment length */
- offset += length;
- /* For 1st iteration only, adjust to create stagger */
- if (n == 0)
- offset -= length / 2;
-
- }
- }
- return EC_SUCCESS;
+ return (const uint8_t *)memchr(data, '#', 256) - (const uint8_t *)data;
}
-static int test_write_full_multi(void)
+/*
+ * Helper function, depending on the argument value either writes variables
+ * into nvmem and verifies their presence, or deletes them and verifies that
+ * they indeed disappear.
+ */
+static int var_read_write_delete_helper(int do_write)
{
- int n;
- int ret;
+ size_t i;
+ uint16_t saved_total_var_space;
+ uint32_t coverage_map;
+
+ const struct {
+ uint8_t *key;
+ uint8_t *value;
+ } kv_pairs[] = {
+ /* Use # as the delimiter to allow \0 in keys/values. */
+ {"\0key\00#", "value of key2#"}, {"key1#", "value of key1#"},
+ {"key2#", "value of key2#"}, {"key3#", "value of\0 key3#"},
+ {"ke\04#", "value\0 of\0 key4#"},
+ };
+
+ coverage_map = 0;
+ saved_total_var_space = total_var_space;
/*
- * The purpose of this test is to completely fill each user buffer in
- * NvMem with random data a segment length at a time. The data written
- * to NvMem is saved in write_buffer[] and then can be used to check the
- * NvMem writes were successful by reading and then comparing each user
- * buffer.
+ * Read all vars, one at a time, verifying that they shows up in
+ * getvar results when appropriate but not before.
*/
- for (n = 0; n < NVMEM_NUM_USERS; n++) {
- ret = write_full_buffer(nvmem_user_sizes[n], n);
- if (ret != EC_SUCCESS)
- return ret;
+ for (i = 0; i <= ARRAY_SIZE(kv_pairs); i++) {
+ size_t j;
+ uint8_t key_len;
+ uint8_t val_len;
+ const void *value;
+
+ for (j = 0; j < ARRAY_SIZE(kv_pairs); j++) {
+ struct tuple *t;
+
+ coverage_map |= 1;
+
+ key_len = find_lb(kv_pairs[j].key);
+ t = getvar(kv_pairs[j].key, key_len);
+
+ if ((j >= i) ^ !do_write) {
+ TEST_ASSERT(t == NULL);
+ continue;
+ }
+
+ coverage_map |= 2;
+
+ TEST_ASSERT(saved_total_var_space == total_var_space);
+
+ /* Confirm that what we found is the right variable. */
+ val_len = find_lb(kv_pairs[j].value);
+
+ TEST_ASSERT(t->key_len == key_len);
+ TEST_ASSERT(t->val_len == val_len);
+ TEST_ASSERT(
+ !memcmp(kv_pairs[j].key, t->data_, key_len));
+ TEST_ASSERT(!memcmp(kv_pairs[j].value,
+ t->data_ + key_len, val_len));
+ freevar(t);
+ }
+
+ if (i == ARRAY_SIZE(kv_pairs)) {
+ coverage_map |= 4;
+ /* All four variables have been processed. */
+ break;
+ }
+
+ val_len = find_lb(kv_pairs[i].value);
+ key_len = find_lb(kv_pairs[i].key);
+ value = kv_pairs[i].value;
+ if (!do_write) {
+
+ coverage_map |= 8;
+
+ saved_total_var_space -= val_len + key_len;
+ /*
+ * Make sure all val_len == 0 and val == NULL
+ * combinations are exercised.
+ */
+ switch (i) {
+ case 0:
+ val_len = 0;
+ coverage_map |= 0x10;
+ break;
+
+ case 1:
+ coverage_map |= 0x20;
+ value = NULL;
+ break;
+ default:
+ coverage_map |= 0x40;
+ val_len = 0;
+ value = NULL;
+ break;
+ }
+ } else {
+ coverage_map |= 0x80;
+ saved_total_var_space += val_len + key_len;
+ }
+ key_len = find_lb(kv_pairs[i].key);
+ TEST_ASSERT(setvar(kv_pairs[i].key, key_len, value, val_len) ==
+ EC_SUCCESS);
+
+ TEST_ASSERT(saved_total_var_space == total_var_space);
}
+
+ if (do_write)
+ TEST_ASSERT(coverage_map == 0x87);
+ else
+ TEST_ASSERT(coverage_map == 0x7f);
+
return EC_SUCCESS;
}
-static int test_write_fail(void)
+static int test_var_read_write_delete(void)
{
- uint32_t offset = 0;
- uint32_t num_bytes = 0x200;
- int ret;
+ TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS);
- /* Do write/read sequence that's expected to be successful */
- if (test_write_read(offset, num_bytes, NVMEM_USER_0))
- return EC_ERROR_UNKNOWN;
+ ccprintf("\n%s: starting write cycle\n", __func__);
+ TEST_ASSERT(var_read_write_delete_helper(1) == EC_SUCCESS);
- /* Prevent flash erase/write operations */
- flash_write_fail = 1;
- /* Attempt flash write */
- ret = test_write_read(offset, num_bytes, NVMEM_USER_0);
- /* Resume normal operation */
- flash_write_fail = 0;
+ ccprintf("%s: starting delete cycle\n", __func__);
+ TEST_ASSERT(var_read_write_delete_helper(0) == EC_SUCCESS);
+
+ return EC_SUCCESS;
+}
+/* Verify that nvmem_erase_user_data only erases the given user's data. */
+static int test_nvmem_erase_tpm_data(void)
+{
+ TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ browse_flash_contents(1);
+ TEST_ASSERT(nvmem_erase_tpm_data() == EC_SUCCESS);
+ browse_flash_contents(1);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(test_result.deleted_obj_count == 0);
+ TEST_ASSERT(test_result.var_count == 3);
+ TEST_ASSERT(test_result.reserved_obj_count == 0);
+ TEST_ASSERT(test_result.evictable_obj_count == 0);
+ TEST_ASSERT(test_result.unexpected_count == 0);
+ TEST_ASSERT(test_result.valid_data_size == 86);
+ TEST_ASSERT(test_result.erased_data_size == 0);
- /* This test is successful if write attempt failed */
- return !ret;
+ return EC_SUCCESS;
}
-static int test_buffer_overflow(void)
+static size_t fill_obj_offsets(uint16_t *offsets, size_t max_objects)
{
- int ret;
- int n;
+ size_t i;
+ size_t obj_count;
- /*
- * The purpose of this test is to check that NvMem writes behave
- * properly in relation to the defined length of each user buffer. A
- * write operation to completely fill the buffer is done first. This
- * should pass. Then the same buffer is written to with one extra byte
- * and this operation is expected to fail.
- */
+ obj_count = init_object_offsets(offsets, max_objects);
- /* Do test for each user buffer */
- for (n = 0; n < NVMEM_NUM_USERS; n++) {
- /* Write full buffer */
- ret = write_full_buffer(nvmem_user_sizes[n], n);
- if (ret != EC_SUCCESS)
- return ret;
- /* Attempt to write full buffer plus 1 extra byte */
- ret = write_full_buffer(nvmem_user_sizes[n] + 1, n);
- if (!ret)
- return EC_ERROR_UNKNOWN;
+ ccprintf("%d objects\n", obj_count);
+ for (i = 0; i < obj_count; i++) {
+ uint32_t *op;
+
+ op = evictable_offs_to_addr(offsets[i]);
+ ccprintf("offs %04x:%08x:%08x:%08x addr %p size %d\n",
+ offsets[i], op[-1], op[0], op[1], op,
+ (uintptr_t)nvmem_cache_base(NVMEM_TPM) + op[-1] -
+ (uintptr_t)op);
}
- /* Test case where user buffer number is valid */
- ret = test_write_read(0, 0x100, NVMEM_USER_0);
- if (ret != EC_SUCCESS)
- return ret;
- /* Attempt same write, but with invalid user number */
- ret = test_write_read(0, 0x100, NVMEM_NUM_USERS);
- if (!ret)
- return ret;
+ return obj_count;
+}
- return EC_SUCCESS;
+static size_t fill_cache_offsets(const void *cache, uint16_t *offsets,
+ size_t max_objects)
+{
+ uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
+ void *real_cache;
+ size_t num_offsets;
+
+ real_cache = nvmem_cache_base(NVMEM_TPM);
+ memcpy(buf, real_cache, sizeof(buf));
+
+ memcpy(real_cache, cache, sizeof(buf));
+ memset(offsets, 0, sizeof(*offsets) * max_objects);
+ num_offsets = fill_obj_offsets(offsets, max_objects);
+
+ /* Restore the real cache. */
+ memcpy(real_cache, buf, sizeof(buf));
+
+ return num_offsets;
}
+#define MAX_OFFSETS 20
-static int test_move(void)
+static uint32_t get_evict_size(const uint8_t *cache, uint16_t offset)
{
- uint32_t len = 0x100;
- uint32_t nv1_offset;
- uint32_t nv2_offset;
- int user = 0;
- int n;
- int ret;
+ uint32_t next_addr;
+ uint32_t cache_offset;
- /*
- * The purpose of this test is to check that nvmem_move() behaves
- * properly. This test only uses one user buffer as accessing multiple
- * user buffers is tested separately. This test uses writes a set of
- * test data then test move operations with full overlap, half overlap
- * and no overlap. Folliwng these tests, the boundary conditions for
- * move operations are checked for the giver user buffer.
- */
+ cache_offset = s_evictNvStart + offset;
+ memcpy(&next_addr, cache + cache_offset - sizeof(next_addr),
+ sizeof(next_addr));
+
+ return next_addr - cache_offset;
+}
+
+/* Returns zero if the two objects are identical. */
+static int compare_objects(const uint8_t *cache1, uint16_t offset1,
+ const uint8_t *cache2, uint16_t offset2)
+{
+ uint32_t size1;
+ uint32_t size2;
+
+ size1 = get_evict_size(cache1, offset1);
+ size2 = get_evict_size(cache2, offset2);
+
+ if (size1 == size2)
+ return memcmp(cache1 + s_evictNvStart + offset1,
+ cache2 + s_evictNvStart + offset2, size1);
+
+ return 1;
+}
+/*
+ * Compare two instances of NVMEM caches. Reserved spaces should be exactly
+ * the same for the match, but evictable objects could be rearranged due to
+ * compaction, updating, etc.
+ *
+ * For the two cache instances to be considered the same the sets and contents
+ * of the evictable object spaces must also match object to object.
+ */
+static int caches_match(const uint8_t *cache1, const uint8_t *cache2)
+{
+ int failed_count;
+ size_t cache1_offs_count;
+ size_t cache2_offs_count;
+ size_t i;
+ uint16_t cache1_offsets[MAX_OFFSETS];
+ uint16_t cache2_offsets[MAX_OFFSETS];
+
+ for (failed_count = i = 0; i < NV_PSEUDO_RESERVE_LAST; i++) {
+ NV_RESERVED_ITEM ri;
+ struct {
+ uint32_t offset;
+ uint32_t size;
+ } ranges[3];
+ size_t j;
+
+ NvGetReserved(i, &ri);
+
+ ranges[0].offset = ri.offset;
+
+ if (i != NV_STATE_CLEAR) {
+ ranges[0].size = ri.size;
+ ranges[1].size = 0;
+ } else {
+ ranges[0].size = offsetof(STATE_CLEAR_DATA, pcrSave);
+ ranges[1].offset = ranges[0].offset + ranges[0].size;
+ ranges[1].size = sizeof(PCR_SAVE);
+ ranges[2].offset = ranges[1].offset + ranges[1].size;
+ ranges[2].size = sizeof(PCR_AUTHVALUE);
+ }
+
+ for (j = 0; j < ARRAY_SIZE(ranges); j++) {
+
+ uint32_t offset;
+ uint32_t size;
+ uint32_t k;
+
+ size = ranges[j].size;
+ if (!size)
+ break;
+
+ offset = ranges[j].offset;
- nv1_offset = 0;
- for (n = 0; n < 3; n++) {
- /* Generate Test data */
- generate_random_data(nv1_offset, len);
- nv2_offset = nv1_offset + (len / 2) * n;
- /* Write data to Nvmem cache memory */
- nvmem_write(nv1_offset, len, &write_buffer[nv1_offset], user);
- nvmem_commit();
- /* Test move while data is in cache area */
- nvmem_move(nv1_offset, nv2_offset, len, user);
- nvmem_read(nv2_offset, len, read_buffer, user);
- if (memcmp(write_buffer, read_buffer, len))
- return EC_ERROR_UNKNOWN;
- ccprintf("Memmove nv1 = 0x%x, nv2 = 0x%x\n",
- nv1_offset, nv2_offset);
+ if (!memcmp(cache1 + offset, cache2 + offset, size))
+ continue;
+
+ ccprintf("%s:%d failed comparing %d:%d:\n", __func__,
+ __LINE__, i, j);
+ for (k = offset; k < (offset + size); k++)
+ if (cache1[k] != cache2[k])
+ ccprintf(" %3d:%02x", k - offset,
+ cache1[k]);
+ ccprintf("\n");
+ for (k = offset; k < (offset + size); k++)
+ if (cache1[k] != cache2[k])
+ ccprintf(" %3d:%02x", k - offset,
+ cache2[k]);
+ ccprintf("\n");
+
+ failed_count++;
+ }
}
- /* Test invalid buffer offsets */
- /* Destination offset is equal to length of buffer */
- nv1_offset = 0;
- nv2_offset = nvmem_user_sizes[user];
- /* Attempt to move just 1 byte */
- ret = nvmem_move(nv1_offset, nv2_offset, 1, user);
- if (!ret)
- return EC_ERROR_UNKNOWN;
-
- /* Source offset is equal to length of buffer */
- nv1_offset = nvmem_user_sizes[user];
- nv2_offset = 0;
- /* Attempt to move just 1 byte */
- ret = nvmem_move(nv1_offset, nv2_offset, 1, user);
- if (!ret)
- return EC_ERROR_UNKNOWN;
-
- nv1_offset = 0;
- nv2_offset = nvmem_user_sizes[user] - len;
- /* Move data chunk from start to end of buffer */
- ret = nvmem_move(nv1_offset, nv2_offset,
- len, user);
- if (ret)
- return ret;
-
- /* Attempt to move data chunk 1 byte beyond end of user buffer */
- nv1_offset = 0;
- nv2_offset = nvmem_user_sizes[user] - len + 1;
- ret = nvmem_move(nv1_offset, nv2_offset,
- len, user);
- if (!ret)
- return EC_ERROR_UNKNOWN;
- /* nvmem_move returned an error, need to clear internal error state */
- nvmem_commit();
+ TEST_ASSERT(!failed_count);
+
+ cache1_offs_count = fill_cache_offsets(cache1, cache1_offsets,
+ ARRAY_SIZE(cache1_offsets));
+ cache2_offs_count = fill_cache_offsets(cache2, cache2_offsets,
+ ARRAY_SIZE(cache2_offsets));
+
+ TEST_ASSERT(cache1_offs_count == cache2_offs_count);
+
+ for (i = 0; (i < ARRAY_SIZE(cache1_offsets)) && cache2_offs_count;
+ i++) {
+ size_t j;
+
+ for (j = 0; j < cache2_offs_count; j++) {
+ if (compare_objects(cache1, cache1_offsets[i], cache2,
+ cache2_offsets[j]))
+ continue;
+ /* Remove object from the cache2 offsets. */
+ cache2_offsets[j] = cache2_offsets[--cache2_offs_count];
+ break;
+ }
+ }
+
+ TEST_ASSERT(cache2_offs_count == 0);
return EC_SUCCESS;
}
-static int test_is_different(void)
+static int prepare_post_migration_nvmem(void)
{
- uint32_t len = 0x41;
- uint32_t nv1_offset = 0;
- int user = 1;
- int ret;
+ TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ return EC_SUCCESS;
+}
+/*
+ * This test creates various failure conditions related to interrupted nvmem
+ * save operations and verifies that transaction integrity is maintained -
+ * i.e. either all variables get updated,
+ */
+static int test_nvmem_incomplete_transaction(void)
+{
/*
- * The purpose of this test is to verify nv_is_different(). Test data is
- * written to a location in user buffer 1, then a case that's expected
- * to pass along with a case that is expected to fail are checked. Next
- * the same tests are repeated when the NvMem write is followed by a
- * commit operation.
+ * Will be more than enough, we can't store more than 15 objects or so
+ * anyways.
*/
+ uint16_t offsets[MAX_OFFSETS];
+ size_t num_objects;
+ uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
+
+ TEST_ASSERT(prepare_post_migration_nvmem() == EC_SUCCESS);
+ num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
+ TEST_ASSERT(num_objects == 9);
+
+ /* Save cache state before deleting objects. */
+ memcpy(buf, nvmem_cache_base(NVMEM_TPM), sizeof(buf));
+
+ drop_evictable_obj(evictable_offs_to_addr(offsets[4]));
+ drop_evictable_obj(evictable_offs_to_addr(offsets[3]));
+
+ failure_mode = TEST_FAIL_WHEN_SAVING;
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ wipe_out_nvmem_cache();
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ TEST_ASSERT(caches_match(buf, nvmem_cache_base(NVMEM_TPM)) ==
+ EC_SUCCESS);
+ drop_evictable_obj(evictable_offs_to_addr(offsets[4]));
+ drop_evictable_obj(evictable_offs_to_addr(offsets[3]));
+
+ /* Check if failure when invalidating is recovered after restart. */
+ failure_mode = TEST_FAIL_WHEN_INVALIDATING;
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ ccprintf("%s:%d\n", __func__, __LINE__);
+ wipe_out_nvmem_cache();
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ ccprintf("%s:%d\n", __func__, __LINE__);
+ num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
+ TEST_ASSERT(num_objects == 7);
- /* Generate test data */
- generate_random_data(nv1_offset, len);
- /* Write to NvMem cache buffer */
- nvmem_write(nv1_offset, len, &write_buffer[nv1_offset], user);
- /* Expected to be the same */
- ret = nvmem_is_different(nv1_offset, len,
- &write_buffer[nv1_offset], user);
- if (ret)
- return EC_ERROR_UNKNOWN;
-
- /* Expected to be different */
- ret = nvmem_is_different(nv1_offset + 1, len,
- &write_buffer[nv1_offset], user);
- if (!ret)
- return EC_ERROR_UNKNOWN;
-
- /* Commit cache buffer and retest */
- nvmem_commit();
- /* Expected to be the same */
- ret = nvmem_is_different(nv1_offset, len,
- &write_buffer[nv1_offset], user);
- if (ret)
- return EC_ERROR_UNKNOWN;
-
- /* Expected to be different */
- write_buffer[nv1_offset] ^= 0xff;
- ret = nvmem_is_different(nv1_offset, len,
- &write_buffer[nv1_offset], user);
- if (!ret)
- return EC_ERROR_UNKNOWN;
+ return EC_SUCCESS;
+}
+
+/*
+ * Verify that interrupted compaction results in a consistent state of the
+ * NVMEM cache.
+ */
+static int test_nvmem_interrupted_compaction(void)
+{
+ uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
+ uint8_t target_list_index;
+ uint8_t filler = 1;
+ TEST_ASSERT(prepare_post_migration_nvmem() == EC_SUCCESS);
+
+ /* Let's fill up a couple of pages with erased objects. */
+ target_list_index = master_at.list_index + 2;
+
+ do {
+ /*
+ * A few randomly picked reserved objects to modify to create
+ * need for compaction.
+ */
+ const uint8_t objs_to_modify[] = {1, 3, 19, 42};
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(objs_to_modify); i++) {
+ NV_RESERVED_ITEM ri;
+
+ NvGetReserved(i, &ri);
+
+ /* Direct access to the object. */
+ memset((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
+ ri.offset,
+ filler++, ri.size);
+ }
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ } while (master_at.list_index != target_list_index);
+
+ /* Save the state of NVMEM cache. */
+ memcpy(buf, nvmem_cache_base(NVMEM_TPM), sizeof(buf));
+ failure_mode = TEST_FAIL_WHEN_COMPACTING;
+ compact_nvmem();
+ wipe_out_nvmem_cache();
+ ccprintf("%s:%d\n", __func__, __LINE__);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(caches_match(buf, nvmem_cache_base(NVMEM_TPM)) ==
+ EC_SUCCESS);
return EC_SUCCESS;
}
int nvmem_first_task(void *unused)
{
- uint32_t offset = 0;
- uint32_t num_bytes = WRITE_SEGMENT_LEN;
- int user = NVMEM_USER_0;
-
- task_wait_event(0);
- /* Generate source data */
- generate_random_data(0, num_bytes);
- nvmem_write(0, num_bytes, &write_buffer[offset], user);
- /* Read from cache memory */
- nvmem_read(0, num_bytes, read_buffer, user);
- /* Verify that write to nvmem was successful */
- TEST_ASSERT_ARRAY_EQ(write_buffer, read_buffer, num_bytes);
- /* Wait here with mutex held by this task */
- task_wait_event(0);
- /* Write to flash which releases nvmem mutex */
- nvmem_commit();
- nvmem_read(0, num_bytes, read_buffer, user);
- /* Verify that write to flash was successful */
- TEST_ASSERT_ARRAY_EQ(write_buffer, read_buffer, num_bytes);
-
return EC_SUCCESS;
}
int nvmem_second_task(void *unused)
{
- uint32_t offset = WRITE_SEGMENT_LEN;
- uint32_t num_bytes = WRITE_SEGMENT_LEN;
- int user = NVMEM_USER_0;
-
- task_wait_event(0);
-
- /* Gen test data and don't overwite test data generated by 1st task */
- generate_random_data(offset, num_bytes);
- /* Write test data at offset 0 nvmem user buffer */
- nvmem_write(0, num_bytes, &write_buffer[offset], user);
- /* Write to flash */
- nvmem_commit();
- /* Read from nvmem */
- nvmem_read(0, num_bytes, read_buffer, user);
- /* Verify that write to nvmem was successful */
- TEST_ASSERT_ARRAY_EQ(&write_buffer[offset], read_buffer, num_bytes);
- /* Clear flag to indicate lock test is complete */
- lock_test_started = 0;
-
return EC_SUCCESS;
}
-static int test_lock(void)
+static void run_test_setup(void)
{
- /*
- * This purpose of this test is to verify the mutex lock portion of the
- * nvmem module. There are two additional tasks utilized. The first task
- * is woken and it creates some test data and does an
- * nvmem_write(). This will cause the mutex to be locked by the 1st
- * task. The 1st task then waits and control is returned to this
- * function and the 2nd task is woken, the 2nd task also attempts to
- * write data to nvmem. The 2nd task should stall waiting for the mutex
- * to be unlocked.
- *
- * When control returns to this function, the 1st task is woken again
- * and the nvmem operation is completed. This will allow the 2nd task to
- * grab the lock and finish its nvmem operation. The test will not
- * complete until the 2nd task finishes the nvmem write. A static global
- * flag is used to let this function know when the 2nd task is complete.
- *
- * Both tasks write to the same location in nvmem so the test will only
- * pass if the 2nd task can't write until the nvmem write in the 1st
- * task is completed.
- */
+ /* Allow Flash erase/writes */
+ flash_write_fail = 0;
+ test_reset();
+}
- /* Set flag for start of test */
- lock_test_started = 1;
- /* Wake first_task */
- task_wake(TASK_ID_NV_1);
- task_wait_event(1000);
- /* Wake second_task. It should stall waiting for mutex */
- task_wake(TASK_ID_NV_2);
- task_wait_event(1000);
- /* Go back to first_task so it can complete its nvmem operation */
- task_wake(TASK_ID_NV_1);
- /* Wait for 2nd task to complete nvmem operation */
- while (lock_test_started)
- task_wait_event(100);
+void nvmem_wipe_cache(void)
+{
+}
- return EC_SUCCESS;
+int DCRYPTO_ladder_is_enabled(void)
+{
+ return 1;
}
-static int test_nvmem_save(void)
+static int test_migration(void)
{
/*
- * The purpose of this test is to verify that if the written value
- * did not change the cache contents there is no actual write
- * happening at the commit time.
+ * This purpose of this test is to verify migration of the 'legacy'
+ * TPM NVMEM format to the new scheme where each element is stored in
+ * flash in its own container.
*/
- int dummy_value;
- int offset = 0x10;
- uint8_t generation_a;
- uint8_t generation_b;
- uint8_t prev_generation;
- uint8_t new_generation;
- const struct nvmem_tag *part_a;
- const struct nvmem_tag *part_b;
- const struct nvmem_tag *new_gen_part;
- const struct nvmem_tag *prev_gen_part;
-
- part_a = (const struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_A;
- part_b = (const struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_B;
+ TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
+ TEST_ASSERT(test_result.var_count == 3);
+ TEST_ASSERT(test_result.reserved_obj_count == 40);
+ TEST_ASSERT(test_result.evictable_obj_count == 9);
+ TEST_ASSERT(test_result.delimiter_count == 1);
+ TEST_ASSERT(test_result.deleted_obj_count == 0);
+ TEST_ASSERT(test_result.unexpected_count == 0);
+ TEST_ASSERT(test_result.valid_data_size == 5214);
+ TEST_ASSERT(total_var_space == 77);
+ /* Container pointer not yet set. */
+ TEST_ASSERT(!master_at.ct.data_offset && !master_at.ct.ph);
+ return EC_SUCCESS;
+}
+
+/*
+ * The purpose of this test is to verify variable storage limits, both per
+ * object and total.
+ */
+static int test_var_boundaries(void)
+{
+ const size_t max_size = 255; /* Key and value must fit in a byte. */
+ const uint8_t *key;
+ const uint8_t *val;
+ size_t key_len;
+ size_t val_len;
+ uint16_t saved_total_var_space;
+ uint32_t coverage_map;
+ uint8_t var_key[10];
+
+ TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
+ saved_total_var_space = total_var_space;
+ coverage_map = 0;
+
/*
- * Make sure nvmem is initialized and both partitions have been
- * written.
+ * Let's use the legacy NVMEM image as a source of fairly random but
+ * reproducible data.
*/
- nvmem_init();
+ key = legacy_nvmem_image;
+ val = legacy_nvmem_image;
/*
- * Make sure something is changed at offset 0x10 into the second user
- * space.
+ * Test limit of max variable body space, use keys and values of
+ * different sizes, below and above the limit.
*/
- nvmem_read(offset, sizeof(dummy_value), &dummy_value, NVMEM_USER_1);
- dummy_value ^= ~0;
- nvmem_write(0x10, sizeof(dummy_value), &dummy_value, NVMEM_USER_1);
- nvmem_commit();
+ for (key_len = 1; key_len < max_size; key_len += 20) {
+
+ coverage_map |= 1;
+
+ val_len = MIN(max_size, MAX_VAR_BODY_SPACE - key_len);
+ TEST_ASSERT(setvar(key, key_len, val, val_len) == EC_SUCCESS);
+ TEST_ASSERT(total_var_space ==
+ saved_total_var_space + key_len + val_len);
- /* Verify that the two generation values are different. */
- generation_a = part_a->generation;
- generation_b = part_b->generation;
- TEST_ASSERT(generation_a != generation_b);
+ /* Now drop the variable from the storage. */
+ TEST_ASSERT(setvar(key, key_len, NULL, 0) == EC_SUCCESS);
+ TEST_ASSERT(total_var_space == saved_total_var_space);
+
+ /* And if key length allows it, try to write too much. */
+ if (val_len == max_size)
+ continue;
+
+ coverage_map |= 2;
+ /*
+ * Yes, let's try writing one byte too many and see that the
+ * attempt is rejected.
+ */
+ val_len++;
+ TEST_ASSERT(setvar(key, key_len, val, val_len) ==
+ EC_ERROR_INVAL);
+ TEST_ASSERT(total_var_space == saved_total_var_space);
+ }
/*
- * Figure out which one should change next, we are close to the
- * beginnig of the test, no wrap is expected.
+ * Test limit of max total variable space, use keys and values of
+ * different sizes, below and above the limit.
*/
- if (generation_a > generation_b) {
- prev_generation = generation_a;
- new_generation = generation_a + 1;
- new_gen_part = part_b;
- prev_gen_part = part_a;
- } else {
- prev_generation = generation_b;
- new_generation = generation_b + 1;
- new_gen_part = part_a;
- prev_gen_part = part_b;
+ key_len = sizeof(var_key);
+ val_len = 20; /* Anything below 256 would work. */
+ memset(var_key, 'x', key_len);
+
+ while (1) {
+ int rv;
+
+ /*
+ * Change the key so that a new variable is added to the
+ * storage.
+ */
+ rv = setvar(var_key, key_len, val, val_len);
+
+ if (rv == EC_ERROR_OVERFLOW)
+ break;
+
+ coverage_map |= 4;
+ TEST_ASSERT(rv == EC_SUCCESS);
+ var_key[0]++;
+ saved_total_var_space += key_len + val_len;
}
- /* Write a new value, this should trigger generation switch. */
- dummy_value += 1;
- TEST_ASSERT(nvmem_write(0x10, sizeof(dummy_value),
- &dummy_value, NVMEM_USER_1) == EC_SUCCESS);
- TEST_ASSERT(nvmem_commit() == EC_SUCCESS);
+ TEST_ASSERT(saved_total_var_space == total_var_space);
+ TEST_ASSERT(saved_total_var_space <= MAX_VAR_TOTAL_SPACE);
+ TEST_ASSERT((saved_total_var_space + key_len + val_len) >
+ MAX_VAR_TOTAL_SPACE);
- TEST_ASSERT(prev_gen_part->generation == prev_generation);
- TEST_ASSERT(new_gen_part->generation == new_generation);
+ TEST_ASSERT(coverage_map == 7);
+ return EC_SUCCESS;
+}
- /* Write the same value, this should NOT trigger generation switch. */
- TEST_ASSERT(nvmem_write(0x10, sizeof(dummy_value),
- &dummy_value, NVMEM_USER_1) == EC_SUCCESS);
- TEST_ASSERT(nvmem_commit() == EC_SUCCESS);
+static int verify_ram_index_space(size_t verify_size)
+{
+ NV_RESERVED_ITEM ri;
+ size_t i;
+ uint32_t casted_size;
+ uint8_t byte;
+ uint8_t fill_byte = 0x55;
+
+ if (verify_size > RAM_INDEX_SPACE)
+ return EC_ERROR_INVAL;
+
+ NvGetReserved(NV_RAM_INDEX_SPACE, &ri);
+
+ /*
+ * Save the size of the index space, needed on machines where size_t
+ * is a 64 bit value.
+ */
+ casted_size = verify_size;
+
+ /*
+ * Now write index space in the cache, we write the complete space,
+ * but on read back only verify_size bytes are expected to be set.
+ */
+ nvmem_write(ri.offset, sizeof(casted_size), &casted_size, NVMEM_TPM);
+
+ for (i = 0; i < RAM_INDEX_SPACE; i++)
+ nvmem_write(ri.offset + sizeof(casted_size) + i,
+ sizeof(fill_byte), &fill_byte, NVMEM_TPM);
- TEST_ASSERT(prev_gen_part->generation == prev_generation);
- TEST_ASSERT(new_gen_part->generation == new_generation);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ wipe_out_nvmem_cache();
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* Make sure read back size matches. */
+ nvmem_read(ri.offset, sizeof(casted_size), &casted_size, NVMEM_TPM);
+ TEST_ASSERT(casted_size == verify_size);
+
+ /*
+ * Now check spaces which were supposed to be written (up to
+ * verify_size) and left intact.
+ */
+ for (i = 0; i < RAM_INDEX_SPACE; i++) {
+ nvmem_read(ri.offset + sizeof(casted_size) + i, sizeof(byte),
+ &byte, NVMEM_TPM);
+ if (i < verify_size)
+ TEST_ASSERT(byte == fill_byte);
+ else
+ TEST_ASSERT(byte == 0);
+ }
return EC_SUCCESS;
}
-static void run_test_setup(void)
+static int test_tpm_nvmem_modify_reserved_objects(void)
{
- /* Allow Flash erase/writes */
- flash_write_fail = 0;
- test_reset();
+ NV_RESERVED_ITEM ri;
+ /* Some random reserved objects' indices. */
+ const uint8_t res_obj_ids[] = {1, 4, 9, 20};
+ size_t i;
+ static uint8_t cache_copy[12 * 1024];
+ struct nvmem_test_result old_result;
+ uint64_t new_values[ARRAY_SIZE(res_obj_ids)];
+ size_t erased_size;
+
+ TEST_ASSERT(sizeof(cache_copy) >= nvmem_user_sizes[NVMEM_TPM]);
+ TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ iterate_over_flash();
+ old_result = test_result;
+
+ /* Preserve NVMEM cache for future comparison. */
+ memcpy(cache_copy, nvmem_cache_base(NVMEM_TPM),
+ nvmem_user_sizes[NVMEM_TPM]);
+
+ erased_size = 0;
+ /* Modify several reserved objects in the cache. */
+ for (i = 0; i < ARRAY_SIZE(res_obj_ids); i++) {
+ size_t copy_size;
+ uint8_t *addr_in_cache;
+ size_t k;
+
+ NvGetReserved(res_obj_ids[i], &ri);
+ copy_size = MIN(sizeof(new_values[0]), ri.size);
+ addr_in_cache =
+ (uint8_t *)nvmem_cache_base(NVMEM_TPM) + ri.offset;
+
+ /* Prepare a new value for the variable. */
+ memcpy(new_values + i, addr_in_cache, copy_size);
+ for (k = 0; k < copy_size; k++)
+ ((uint8_t *)(new_values + i))[k] ^= 0x55;
+
+ /* Update value in the cache. */
+ memcpy(addr_in_cache, new_values + i, copy_size);
+
+ /* And in the cache copy. */
+ memcpy(cache_copy + ri.offset, new_values + i, copy_size);
+
+ /*
+ * This much will be added to the erased space, object size
+ * plus index size.
+ */
+ erased_size += ri.size + 1;
+ }
+
+ /* Save it into flash. */
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+
+ /* Wipe out the cache to be sure. */
+ wipe_out_nvmem_cache();
+
+ /* Read NVMEM contents from flash. */
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* Verify that the cache matches expectations. */
+ TEST_ASSERT(!memcmp(cache_copy, nvmem_cache_base(NVMEM_TPM),
+ nvmem_user_sizes[NVMEM_TPM]));
+
+ iterate_over_flash();
+
+ /* Update previous results with our expectations. */
+ old_result.deleted_obj_count += ARRAY_SIZE(res_obj_ids);
+ old_result.erased_data_size += erased_size;
+ old_result.delimiter_count++;
+
+ TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
+
+ /* Verify several index space cases. */
+ for (i = 0; i <= RAM_INDEX_SPACE; i += (RAM_INDEX_SPACE / 2))
+ TEST_ASSERT(verify_ram_index_space(i) == EC_SUCCESS);
+
+ return EC_SUCCESS;
}
-void nvmem_wipe_cache(void)
+static int compare_object(uint16_t obj_offset, size_t obj_size, const void *obj)
{
+ uint32_t next_addr;
+
+ memcpy(&next_addr,
+ evictable_offs_to_addr(obj_offset - sizeof(next_addr)),
+ sizeof(next_addr));
+
+ ccprintf("next_addr %x, sum %x size %d\n", next_addr,
+ (s_evictNvStart + obj_offset + obj_size), obj_size);
+ TEST_ASSERT(next_addr == (s_evictNvStart + obj_offset + obj_size));
+
+ if (!memcmp(evictable_offs_to_addr(obj_offset), obj, obj_size))
+ return EC_SUCCESS;
+
+ return EC_ERROR_INVAL;
}
-int DCRYPTO_ladder_is_enabled(void)
+static int test_tpm_nvmem_modify_evictable_objects(void)
{
- return 1;
+ size_t num_objects;
+ uint16_t offsets[MAX_OFFSETS];
+ uint32_t handles[ARRAY_SIZE(offsets)];
+ uint32_t new_evictable_object[30];
+ size_t i;
+ const uint32_t new_obj_handle = 0x100;
+ static uint8_t modified_obj[CONFIG_FLASH_BANK_SIZE];
+ size_t modified_obj_size;
+ uint32_t modified_obj_handle;
+ uint32_t deleted_obj_handle;
+ uint8_t *obj_cache_addr;
+ size_t num_handles;
+ int new_obj_index;
+ int modified_obj_index;
+
+ TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ iterate_over_flash();
+
+ /* Verify that all evictable objects are there. */
+ num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
+ TEST_ASSERT(num_objects == 9);
+ num_handles = num_objects;
+
+ /* Save handles of all objects there are. */
+ for (i = 0; i < num_objects; i++) {
+ memcpy(handles + i, evictable_offs_to_addr(offsets[i]),
+ sizeof(handles[i]));
+ ccprintf("obj %d handle %08x\n", i, handles[i]);
+ }
+ /*
+ * Let's modify the object which currently is stored second in the
+ * stack.
+ */
+ modified_obj_size = offsets[3] - offsets[2] - sizeof(uint32_t);
+
+ /* Modify the object and copy modified value into local buffer. */
+ obj_cache_addr = evictable_offs_to_addr(offsets[2]);
+ memcpy(&modified_obj_handle, obj_cache_addr,
+ sizeof(modified_obj_handle));
+
+ for (i = 0; i < modified_obj_size; i++) {
+ uint8_t c;
+
+ c = obj_cache_addr[i];
+
+ if (i >= sizeof(uint32_t)) { /* Preserve the 4 byte handle. */
+ c ^= 0x55;
+ obj_cache_addr[i] = c;
+ }
+ modified_obj[i] = c;
+ }
+
+ /* Save its handle and then drop the object at offset 5. */
+ memcpy(&deleted_obj_handle, evictable_offs_to_addr(offsets[5]),
+ sizeof(deleted_obj_handle));
+ drop_evictable_obj(evictable_offs_to_addr(offsets[5]));
+
+ /* Prepare the new evictable object, first four bytes are the handle. */
+ for (i = 0; i < ARRAY_SIZE(new_evictable_object); i++)
+ new_evictable_object[i] = new_obj_handle + i;
+
+ /* Add it to the cache. */
+ add_evictable_obj(new_evictable_object, sizeof(new_evictable_object));
+
+ /* Save the new cache state in the flash. */
+ TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
+
+ /* Wipe out NVMEM cache just in case. */
+ wipe_out_nvmem_cache();
+
+ /* Read back from flash into cache. */
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* One object removed, one added, the number should have not changed. */
+ TEST_ASSERT(num_objects ==
+ fill_obj_offsets(offsets, ARRAY_SIZE(offsets)));
+
+ new_obj_index = 0;
+ modified_obj_index = 0;
+ for (i = 0; i < num_objects; i++) {
+ uint32_t handle;
+ size_t j;
+
+ memcpy(&handle, evictable_offs_to_addr(offsets[i]),
+ sizeof(handles[i]));
+ ASSERT(handle != deleted_obj_handle);
+
+ if (handle == new_obj_handle)
+ new_obj_index = i;
+ else if (handle == modified_obj_handle)
+ modified_obj_index = i;
+ /*
+ * Remove the found handle from the set of handles which were
+ * there originally.
+ */
+ for (j = 0; j < num_handles; j++)
+ if (handles[j] == handle) {
+ num_handles--;
+ handles[j] = handles[num_handles];
+ break;
+ }
+ }
+
+ /*
+ * Removed object's handle is still in the array, and it should be the
+ * only remaining element.
+ */
+ TEST_ASSERT(num_handles == 1);
+ TEST_ASSERT(handles[0] == deleted_obj_handle);
+ TEST_ASSERT(new_obj_index >= 0); /* New handle was seen in the cache. */
+ TEST_ASSERT(modified_obj_index >=
+ 0); /* Modified object was seen in the cache. */
+
+ TEST_ASSERT(compare_object(offsets[new_obj_index],
+ sizeof(new_evictable_object),
+ new_evictable_object) == EC_SUCCESS);
+ TEST_ASSERT(compare_object(offsets[modified_obj_index],
+ modified_obj_size,
+ modified_obj) == EC_SUCCESS);
+ return EC_SUCCESS;
}
void run_test(void)
{
run_test_setup();
+
+ if (0) {
+ RUN_TEST(test_nvmem_incomplete_transaction);
+ test_print_result();
+ return;
+ }
+ RUN_TEST(test_migration);
RUN_TEST(test_corrupt_nvmem);
RUN_TEST(test_fully_erased_nvmem);
RUN_TEST(test_configured_nvmem);
- RUN_TEST(test_write_read_sequence);
- RUN_TEST(test_write_full_multi);
- RUN_TEST(test_write_fail);
- RUN_TEST(test_buffer_overflow);
- RUN_TEST(test_move);
- RUN_TEST(test_is_different);
- RUN_TEST(test_lock);
- RUN_TEST(test_nvmem_erase_user_data);
RUN_TEST(test_nvmem_save);
+ RUN_TEST(test_var_read_write_delete);
+ RUN_TEST(test_nvmem_compaction);
+ RUN_TEST(test_var_boundaries);
+ RUN_TEST(test_nvmem_erase_tpm_data);
+ RUN_TEST(test_tpm_nvmem_modify_reserved_objects);
+ RUN_TEST(test_tpm_nvmem_modify_evictable_objects);
+ RUN_TEST(test_nvmem_incomplete_transaction);
+ failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
+ RUN_TEST(test_nvmem_interrupted_compaction);
+ failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
+
+ /*
+ * more tests to come
+ * RUN_TEST(test_lock);
+ * RUN_TEST(test_malloc_blocking);
+ */
+
test_print_result();
}
diff --git a/test/nvmem_test.h b/test/nvmem_test.h
new file mode 100644
index 0000000000..f8f166dc5e
--- /dev/null
+++ b/test/nvmem_test.h
@@ -0,0 +1,28 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __EC_TEST_NVMEM_TEST_H
+#define __EC_TEST_NVMEM_TEST_H
+
+#define EMBEDDED_MODE 1
+#define NV_C
+#include "Global.h"
+#undef NV_C
+#include "NV_fp.h"
+#include "tpm_generated.h"
+
+enum test_failure_mode {
+ TEST_NO_FAILURE,
+ TEST_FAIL_WHEN_SAVING,
+ TEST_FAIL_WHEN_INVALIDATING,
+ TEST_FAIL_WHEN_COMPACTING
+};
+
+extern enum test_failure_mode failure_mode;
+
+size_t add_evictable_obj(void *obj, size_t obj_size);
+void drop_evictable_obj(void *obj);
+
+#endif /* ! __EC_TEST_NVMEM_TEST_H */
diff --git a/test/nvmem_tpm2_mock.c b/test/nvmem_tpm2_mock.c
new file mode 100644
index 0000000000..070525406d
--- /dev/null
+++ b/test/nvmem_tpm2_mock.c
@@ -0,0 +1,377 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/* Stuff from tpm2 directory. */
+
+#include "nvmem_test.h"
+
+#include "console.h"
+#include "nvmem.h"
+#include "util.h"
+
+#define NVMEM_CR50_SIZE 272
+
+uint32_t s_evictNvStart;
+uint32_t s_evictNvEnd;
+
+/* Calculate size of TPM NVMEM. */
+#define MOCK_NV_MEMORY_SIZE \
+ (NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag) - NVMEM_CR50_SIZE)
+
+uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {MOCK_NV_MEMORY_SIZE,
+ NVMEM_CR50_SIZE};
+
+/*
+ * Sizes of the reserved objects stored in the TPM NVMEM. Note that the second
+ * last object is in fact a variable size field starting with 4 bytes of size
+ * and then up to 512 bytes of actual index data. The array below assumes that
+ * the full 512 bytes of the index space are used.
+ */
+const uint16_t res_sizes[] = {4, 2, 2, 2, 66, 66, 66, 66, 66, 66,
+ 34, 34, 34, 66, 66, 66, 8, 4, 134, 28,
+ 3, 4, 4, 4, 4, 4, 2, 15, 2, 8,
+ 4, 4, 4, 96, 2844, 424, 516, 8};
+
+static uint16_t res_addrs[ARRAY_SIZE(res_sizes)];
+
+BOOL NvEarlyStageFindHandle(TPM_HANDLE handle)
+{
+ size_t i;
+
+ res_addrs[0] = 0;
+
+ for (i = 1; i < ARRAY_SIZE(res_addrs); i++)
+ res_addrs[i] = res_addrs[i - 1] + res_sizes[i - 1];
+
+ s_evictNvStart = res_addrs[i - 1] + res_sizes[i - 1];
+
+ s_evictNvEnd = MOCK_NV_MEMORY_SIZE;
+ return 0;
+}
+
+void NvGetReserved(UINT32 index, NV_RESERVED_ITEM *ri)
+{
+ uint32_t index_size;
+
+ if (index >= ARRAY_SIZE(res_sizes)) {
+ ri->size = 0;
+ return;
+ }
+
+ ri->offset = res_addrs[index];
+ if (index != NV_RAM_INDEX_SPACE) {
+ ri->size = res_sizes[index];
+ return;
+ }
+
+ memcpy(&index_size, nvmem_cache_base(NVMEM_TPM) + ri->offset,
+ sizeof(index_size));
+
+ if (index_size == ~0)
+ /* Must be starting with empty flash memeory. */
+ index_size = 0;
+
+ ri->size = index_size + sizeof(index_size);
+}
+
+UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size)
+{
+ uint16_t value;
+
+ if (!size || (*size < sizeof(value)))
+ return 0;
+
+ value = htobe16(*source);
+
+ memcpy(*buffer, &value, sizeof(value));
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return sizeof(value);
+}
+
+UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size)
+{
+ uint32_t value;
+
+ if (!size || (*size < sizeof(value)))
+ return 0;
+
+ value = htobe32(*source);
+
+ memcpy(*buffer, &value, sizeof(value));
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return sizeof(value);
+}
+
+UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size)
+{
+ uint64_t value;
+
+ if (!size || (*size < sizeof(value)))
+ return 0;
+
+ value = htobe64(*source);
+
+ memcpy(*buffer, &value, sizeof(value));
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return sizeof(value);
+}
+
+UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size)
+{
+ UINT16 total_size;
+ INT32 i;
+ uint8_t *p;
+
+ total_size = UINT16_Marshal(&source->t.size, buffer, size);
+ p = *buffer;
+
+ for (i = 0; (i < source->t.size) && *size; ++i) {
+ *p++ = source->t.buffer[i];
+ *size -= 1;
+ }
+
+ total_size += i;
+ *buffer = p;
+
+ return total_size;
+}
+
+uint16_t TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
+{
+ return TPM2B_DIGEST_Marshal(source, buffer, size);
+}
+
+uint16_t TPM2B_NONCE_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size)
+{
+ return TPM2B_DIGEST_Marshal(source, buffer, size);
+}
+
+TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size)
+{
+ uint16_t value;
+
+ if (!size || *size < sizeof(value))
+ return TPM_RC_INSUFFICIENT;
+
+ memcpy(&value, *buffer, sizeof(value));
+ *target = be16toh(value);
+
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size)
+{
+ uint32_t value;
+
+ if (!size || *size < sizeof(value))
+ return TPM_RC_INSUFFICIENT;
+
+ memcpy(&value, *buffer, sizeof(value));
+ *target = be32toh(value);
+
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size)
+{
+ uint64_t value;
+
+ if (!size || *size < sizeof(value))
+ return TPM_RC_INSUFFICIENT;
+
+ memcpy(&value, *buffer, sizeof(value));
+ *target = be64toh(value);
+
+ *buffer += sizeof(value);
+ *size -= sizeof(value);
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size)
+{
+ TPM_RC result;
+ INT32 i;
+ uint8_t *p;
+
+ result = UINT16_Unmarshal(&target->t.size, buffer, size);
+
+ if (result != TPM_RC_SUCCESS)
+ return result;
+
+ if (target->t.size == 0)
+ return TPM_RC_SUCCESS;
+
+ if ((target->t.size > sizeof(TPMU_HA)) || (target->t.size > *size))
+ return TPM_RC_SIZE;
+
+ p = *buffer;
+ for (i = 0; i < target->t.size; ++i)
+ target->t.buffer[i] = *p++;
+
+ *buffer = p;
+ *size -= i;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
+{
+ return TPM2B_DIGEST_Unmarshal(target, buffer, size);
+}
+
+TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size)
+{
+ return TPM2B_DIGEST_Unmarshal(target, buffer, size);
+}
+
+#define ITER_INIT (~0)
+
+static void *get_cache_addr(size_t offset)
+{
+ return (void *)(((uintptr_t)nvmem_cache_base(NVMEM_TPM)) + offset);
+}
+
+static void read_from_cache(size_t offset, size_t size, void *dest)
+{
+ nvmem_read(offset, size, dest, NVMEM_TPM);
+}
+
+static void write_to_cache(size_t offset, size_t size, void *src)
+{
+ nvmem_write(offset, size, src, NVMEM_TPM);
+}
+
+/* Copies of the appropriate functions from NV.c in TPM2 library. */
+static uint32_t nv_next(uint32_t *iter)
+{
+ uint32_t currentIter;
+
+ if (*iter == ITER_INIT)
+ *iter = s_evictNvStart;
+
+ if ((*iter + sizeof(uint32_t) > s_evictNvEnd) || !*iter)
+ return 0;
+
+ currentIter = *iter;
+ read_from_cache(*iter, sizeof(uint32_t), iter);
+ if (!*iter || (*iter == ITER_INIT))
+ return 0;
+
+ return currentIter + sizeof(uint32_t);
+}
+
+static uint32_t nv_get_end(void)
+{
+ uint32_t iter = ITER_INIT;
+ uint32_t endAddr = s_evictNvStart;
+ uint32_t currentAddr;
+
+ while ((currentAddr = nv_next(&iter)) != 0)
+ endAddr = currentAddr;
+
+ if (endAddr != s_evictNvStart) {
+ /* Read offset. */
+ endAddr -= sizeof(uint32_t);
+ read_from_cache(endAddr, sizeof(uint32_t), &endAddr);
+ }
+ return endAddr;
+}
+
+size_t add_evictable_obj(void *obj, size_t obj_size)
+{
+ uint32_t end_addr;
+ uint32_t next_addr;
+ uint32_t list_end = 0;
+
+ end_addr = nv_get_end();
+
+ next_addr = end_addr + sizeof(uint32_t) + obj_size;
+
+ if (next_addr >= s_evictNvEnd) {
+ ccprintf("%s: could not fit %d bytes!\n", __func__, obj_size);
+ return 0;
+ }
+
+ /* Write next pointer */
+ write_to_cache(end_addr, sizeof(uint32_t), &next_addr);
+ /* Write entity data. */
+ write_to_cache(end_addr + sizeof(uint32_t), obj_size, obj);
+
+ /* Write the end of list if it fits. */
+ if (next_addr + sizeof(uint32_t) <= s_evictNvEnd)
+ write_to_cache(next_addr, sizeof(list_end), &list_end);
+
+ return obj_size;
+}
+
+/*
+ * It is the responsibility of the caller to pass the proper address of an
+ * object in the cache.
+ */
+void drop_evictable_obj(void *obj)
+{
+ uint32_t next_addr;
+ uint32_t list_end = 0;
+ uint32_t obj_addr;
+
+ obj_addr = (uintptr_t)obj - (uintptr_t)nvmem_cache_base(NVMEM_TPM);
+ read_from_cache(obj_addr - sizeof(next_addr), sizeof(next_addr),
+ &next_addr);
+ ccprintf("%s:%d dropping obj at cache addr %x, offset %x, addr %p next "
+ "addr %x aka %x (off s_evictNvStart)\n",
+ __func__, __LINE__, obj_addr - s_evictNvStart, obj_addr, obj,
+ next_addr, next_addr - s_evictNvStart);
+
+ /*
+ * Now, to make it easier to add objects behind the current one, let's
+ * pretend there is no more objects.
+ */
+ write_to_cache(obj_addr - sizeof(next_addr), sizeof(list_end),
+ &list_end);
+
+ if (!next_addr || (next_addr == s_evictNvEnd))
+ return;
+
+ /*
+ * Iterate over objects starting with next_addr, copying them into
+ * obj_addr.
+ */
+ obj_addr = next_addr;
+ while (1) {
+ uint32_t next_next_addr;
+ uint32_t next_obj_size;
+
+ read_from_cache(next_addr, sizeof(next_next_addr),
+ &next_next_addr);
+
+ if (!next_next_addr || (next_next_addr == s_evictNvEnd))
+ return;
+
+ next_obj_size = next_next_addr - obj_addr - sizeof(uint32_t);
+ add_evictable_obj(
+ (void *)((uintptr_t)nvmem_cache_base(NVMEM_TPM) +
+ next_addr + sizeof(uint32_t)),
+ next_obj_size);
+ next_addr = next_next_addr;
+ obj_addr += next_obj_size + sizeof(next_obj_size);
+ }
+}
+
+void *evictable_offs_to_addr(uint16_t offset)
+{
+ return (void *)((uintptr_t)get_cache_addr(s_evictNvStart) + offset);
+}
diff --git a/test/nvmem_vars.c b/test/nvmem_vars.c
deleted file mode 100644
index 99e059215e..0000000000
--- a/test/nvmem_vars.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Test of the key=val variable implementation (set, get, delete, etc).
- */
-
-#include "common.h"
-#include "compile_time_macros.h"
-#include "nvmem.h"
-#include "nvmem_vars.h"
-#include "printf.h"
-#include "shared_mem.h"
-#include "test_util.h"
-
-/* Declare the user regions (see test_config.h) */
-uint32_t nvmem_user_sizes[] = {
- CONFIG_FLASH_NVMEM_VARS_USER_SIZE,
-};
-BUILD_ASSERT(ARRAY_SIZE(nvmem_user_sizes) == NVMEM_NUM_USERS);
-
-/****************************************************************************/
-/* Mock the flash storage */
-
-static uint8_t ram_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE];
-static uint8_t flash_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE];
-
-extern char *rbuf;
-
-/* Internal functions exported for test */
-void release_local_copy(void)
-{
- rbuf = NULL;
-}
-
-int get_local_copy(void)
-{
- if (!rbuf) {
- memcpy(ram_buffer, flash_buffer, sizeof(ram_buffer));
- rbuf = (char *)ram_buffer;
- }
- return EC_SUCCESS;
-}
-
-int nvmem_read(uint32_t startOffset, uint32_t size,
- void *data_, enum nvmem_users user)
-{
- /* Our mocks make some assumptions */
- if (startOffset != 0 ||
- size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE ||
- user != CONFIG_FLASH_NVMEM_VARS_USER_NUM)
- return EC_ERROR_UNIMPLEMENTED;
-
- if (!data_)
- return EC_ERROR_INVAL;
-
- memcpy(data_, flash_buffer, size);
-
- return EC_SUCCESS;
-}
-
-int nvmem_write(uint32_t startOffset, uint32_t size,
- void *data_, enum nvmem_users user)
-{
- /* Our mocks make some assumptions */
- if (startOffset != 0 ||
- size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE ||
- user != CONFIG_FLASH_NVMEM_VARS_USER_NUM)
- return EC_ERROR_UNIMPLEMENTED;
-
- if (!data_)
- return EC_ERROR_INVAL;
-
- memcpy(ram_buffer, data_, size);
-
- return EC_SUCCESS;
-}
-
-int nvmem_commit(void)
-{
- memcpy(flash_buffer, ram_buffer, CONFIG_FLASH_NVMEM_VARS_USER_SIZE);
- return EC_SUCCESS;
-}
-
-int nvmem_erase_user_data(enum nvmem_users user)
-{
- memset(ram_buffer, 0xff, sizeof(ram_buffer));
- memset(flash_buffer, 0xff, sizeof(flash_buffer));
- return EC_SUCCESS;
-}
-
-/****************************************************************************/
-/* Helper routines */
-
-static void erase_flash(void)
-{
- /* Invalidate the RAM cache */
- release_local_copy();
-
- /* Zero flash */
- memset(flash_buffer, 0xff, sizeof(flash_buffer));
-}
-
-/* Erase flash, then copy data_ over it */
-static void load_flash(const uint8_t *data_, size_t data_len)
-{
- erase_flash();
- memcpy(flash_buffer, data_, data_len);
-}
-
-/* Return true if flash matches data_, and is followed by 0xff to the end */
-static int verify_flash(const uint8_t *data_, size_t data_len)
-{
- size_t i;
-
- /* mismatch means false */
- if (memcmp(flash_buffer, data_, data_len))
- return 0;
-
- for (i = data_len;
- i < CONFIG_FLASH_NVMEM_VARS_USER_SIZE - data_len;
- i++)
- if (flash_buffer[i] != 0xff)
- return 0;
- return 1;
-}
-
-/*
- * Treating both as strings, save the <key, value> pair.
- */
-int str_setvar(const char *key, const char *val)
-{
- /* Only for tests, so assume the length will fit */
- uint8_t key_len, val_len;
-
- key_len = strlen(key);
- val_len = val ? strlen(val) : 0;
-
- return setvar(key, key_len, val, val_len);
-}
-
-/*
- * Treating both as strings, lookup the key and compare the result with the
- * expected value. Return true if they match.
- */
-static int str_matches(const char *key, const char *expected_val)
-{
- const struct tuple *t = getvar(key, strlen(key));
- uint8_t expected_len;
-
- if (!expected_val && !t)
- return 1;
-
- if (expected_val && !t)
- return 0;
-
- if (!expected_val && t)
- return 0;
-
- expected_len = strlen(expected_val);
- return !memcmp(tuple_val(t), expected_val, expected_len);
-}
-
-/****************************************************************************/
-/* Tests */
-
-static int check_init(void)
-{
- /* Valid entries */
- const uint8_t good[] = { 0x01, 0x01, 0x00, 'A', 'a',
- 0x01, 0x01, 0x00, 'B', 'b',
- 0x00 };
-
- /* Empty variables are 0x00, followed by all 0xff */
- const uint8_t empty[] = { 0x00 };
-
- /*
- * This is parsed as though there's only one variable, but it's wrong
- * because the rest of the storage isn't 0xff.
- */
- const uint8_t bad_key[] = { 0x01, 0x01, 0x00, 'A', 'a',
- 0x00, 0x01, 0x00, 'B', 'b',
- 0x00 };
-
- /* Zero-length variables are not allowed */
- const uint8_t bad_val[] = { 0x01, 0x01, 0x00, 'A', 'a',
- 0x01, 0x00, 0x00, 'B', 'b',
- 0x00 };
-
- /* The next constants use magic numbers based on on the region size */
- BUILD_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE == 600);
-
- /* This is one byte too large */
- const uint8_t too_big[] = { [0] = 0xff, [1] = 0xff, /* 0 - 512 */
- [513] = 0x01, [514] = 0x53, /* 513 - 599 */
- [599] = 0x00 };
-
- /* This should just barely fit */
- const uint8_t just_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */
- [513] = 0x01, [514] = 0x52, /* 513-598 */
- [599] = 0x00 };
-
- /* No end marker */
- const uint8_t not_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */
- [513] = 0x01, [514] = 0x52, /* 513-598 */
- [599] = 0xff };
-
- load_flash(good, sizeof(good));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(good, sizeof(good)));
-
- load_flash(empty, sizeof(empty));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- /* All 0xff quickly runs off the end of the storage */
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- load_flash(bad_key, sizeof(bad_key));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- load_flash(bad_val, sizeof(bad_val));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- load_flash(too_big, sizeof(too_big));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- load_flash(just_right, sizeof(just_right));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(just_right, sizeof(just_right)));
-
- load_flash(not_right, sizeof(not_right));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- return EC_SUCCESS;
-}
-
-static int simple_search(void)
-{
- const uint8_t preload[] = {
- 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
- 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
- 0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o',
- 0x00 };
-
- load_flash(preload, sizeof(preload));
- TEST_ASSERT(initvars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(preload, sizeof(preload)));
-
- TEST_ASSERT(str_matches("no", 0));
- TEST_ASSERT(str_matches("ho", "yo"));
- TEST_ASSERT(str_matches("yo", "hoyo"));
- TEST_ASSERT(str_matches("mo", "yohoyo"));
-
- return EC_SUCCESS;
-}
-
-static int simple_write(void)
-{
- const uint8_t after_one[] = {
- 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
- 0x00 };
-
- const uint8_t after_two[] = {
- 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
- 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
- 0x00 };
-
- const uint8_t after_three[] = {
- 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o',
- 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o',
- 0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o',
- 0x00 };
-
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- TEST_ASSERT(setvar("ho", 2, "yo", 2) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_one, sizeof(after_one)));
-
- TEST_ASSERT(setvar("yo", 2, "hoyo", 4) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
-
- TEST_ASSERT(setvar("mo", 2, "yohoyo", 6) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_three, sizeof(after_three)));
-
- return EC_SUCCESS;
-}
-
-static int simple_delete(void)
-{
- const char start_with[] = {
- 0x01, 0x05, 0x00, 'A', 'a', 'a', 'a', 'a', 'a',
- 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
- 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
- 0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
- 0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n',
- 0x00 };
-
- const char after_one[] = {
- 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
- 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
- 0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
- 0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n',
- 0x00 };
-
- const char after_two[] = {
- 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
- 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q',
- 0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
- 0x00 };
-
- const char after_three[] = {
- 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b',
- 0x01, 0x03, 0x00, 'M', 'm', '0', 'm',
- 0x00 };
-
- const char empty[] = { 0x00 };
-
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- TEST_ASSERT(setvar("A", 1, "aaaaa", 5) == EC_SUCCESS);
- TEST_ASSERT(setvar("BB", 2, "bbb", 3) == EC_SUCCESS);
- TEST_ASSERT(setvar("CCC", 3, "xyzpdq", 6) == EC_SUCCESS);
- TEST_ASSERT(setvar("M", 1, "m0m", 3) == EC_SUCCESS);
- TEST_ASSERT(setvar("NNNN", 4, "n", 1) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(start_with, sizeof(start_with)));
-
- /* Zap first variable by setting var_len to 0 */
- TEST_ASSERT(setvar("A", 1, "yohoyo", 0) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_one, sizeof(after_one)));
-
- /* Zap last variable by passing null pointer */
- TEST_ASSERT(setvar("NNNN", 4, 0, 3) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
-
- /* Ensure that zapping nonexistant variable does nothing */
- TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_two, sizeof(after_two)));
-
- /* Zap variable in the middle */
- TEST_ASSERT(setvar("CCC", 3, 0, 0) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(after_three, sizeof(after_three)));
-
- /* Zap the rest */
- TEST_ASSERT(setvar("BB", 2, 0, 0) == EC_SUCCESS);
- TEST_ASSERT(setvar("M", 1, 0, 0) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- /* Zapping a nonexistant variable still does nothing */
- TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS);
- TEST_ASSERT(writevars() == EC_SUCCESS);
- TEST_ASSERT(verify_flash(empty, sizeof(empty)));
-
- return EC_SUCCESS;
-}
-
-static int complex_write(void)
-{
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- /* Do a bunch of writes and erases */
- str_setvar("ho", "aa");
- str_setvar("zo", "nn");
- str_setvar("yo", "CCCCCCCC");
- str_setvar("zooo", "yyyyyyy");
- str_setvar("yo", "AA");
- str_setvar("ho", 0);
- str_setvar("yi", "BBB");
- str_setvar("yi", "AA");
- str_setvar("hixx", 0);
- str_setvar("yo", "BBB");
- str_setvar("zo", "");
- str_setvar("hi", "bbb");
- str_setvar("ho", "cccccc");
- str_setvar("yo", "");
- str_setvar("zo", "ggggg");
-
- /* What do we expect to find? */
- TEST_ASSERT(str_matches("hi", "bbb"));
- TEST_ASSERT(str_matches("hixx", 0));
- TEST_ASSERT(str_matches("ho", "cccccc"));
- TEST_ASSERT(str_matches("yi", "AA"));
- TEST_ASSERT(str_matches("yo", 0));
- TEST_ASSERT(str_matches("zo", "ggggg"));
- TEST_ASSERT(str_matches("zooo", "yyyyyyy"));
-
- return EC_SUCCESS;
-}
-
-static int weird_keys(void)
-{
- uint8_t keyA[255];
- uint8_t keyB[255];
- const char *valA = "this is A";
- const char *valB = "THIS IS b";
- int i;
- const struct tuple *t;
-
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- for (i = 0; i < 255; i++) {
- keyA[i] = i;
- keyB[i] = 255 - i;
- }
-
- TEST_ASSERT(setvar(keyA, sizeof(keyA),
- valA, strlen(valA)) == EC_SUCCESS);
-
- TEST_ASSERT(setvar(keyB, sizeof(keyB),
- valB, strlen(valB)) == EC_SUCCESS);
-
- TEST_ASSERT(writevars() == EC_SUCCESS);
-
- t = getvar(keyA, sizeof(keyA));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(valA));
- TEST_ASSERT(memcmp(tuple_val(t), valA, strlen(valA)) == 0);
-
- t = getvar(keyB, sizeof(keyB));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(valB));
- TEST_ASSERT(memcmp(tuple_val(t), valB, strlen(valB)) == 0);
-
- return EC_SUCCESS;
-}
-
-static int weird_values(void)
-{
- const char *keyA = "this is A";
- const char *keyB = "THIS IS b";
- char valA[255];
- char valB[255];
- int i;
- const struct tuple *t;
-
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- for (i = 0; i < 255; i++) {
- valA[i] = i;
- valB[i] = 255 - i;
- }
-
- TEST_ASSERT(setvar(keyA, strlen(keyA),
- valA, sizeof(valA)) == EC_SUCCESS);
- TEST_ASSERT(str_setvar("c", "CcC") == EC_SUCCESS);
- TEST_ASSERT(setvar(keyB, strlen(keyB),
- valB, sizeof(valB)) == EC_SUCCESS);
- TEST_ASSERT(str_setvar("d", "dDd") == EC_SUCCESS);
-
- TEST_ASSERT(writevars() == EC_SUCCESS);
-
- t = getvar(keyA, strlen(keyA));
- TEST_ASSERT(t);
- TEST_ASSERT(memcmp(tuple_val(t), valA, sizeof(valA)) == 0);
-
- t = getvar(keyB, strlen(keyB));
- TEST_ASSERT(t);
- TEST_ASSERT(memcmp(tuple_val(t), valB, sizeof(valB)) == 0);
-
- TEST_ASSERT(str_matches("c", "CcC"));
- TEST_ASSERT(str_matches("d", "dDd"));
-
- return EC_SUCCESS;
-}
-
-static int fill_it_up(void)
-{
- int i, n;
- char key[20];
-
- erase_flash();
- TEST_ASSERT(initvars() == EC_SUCCESS);
-
- /*
- * Some magic numbers here, because we want to use up 10 bytes at a
- * time and end up with exactly 9 free bytes left.
- */
- TEST_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE % 10 == 0);
- n = CONFIG_FLASH_NVMEM_VARS_USER_SIZE / 10;
- TEST_ASSERT(n < 1000);
-
- /* Fill up the storage */
- for (i = 0; i < n - 1; i++) {
- /* 3-byte header, 5-char key, 2-char val, == 10 chars */
- snprintf(key, sizeof(key), "kk%03d", i);
- TEST_ASSERT(setvar(key, 5, "aa", 2) == EC_SUCCESS);
- }
-
- /*
- * Should be nine bytes left in rbuf (because we need one more '\0' at
- * the end). This won't fit.
- */
- TEST_ASSERT(setvar("kk999", 5, "aa", 2) == EC_ERROR_OVERFLOW);
- /* But this will. */
- TEST_ASSERT(setvar("kk999", 5, "a", 1) == EC_SUCCESS);
- /* And this, because it replaces a previous entry */
- TEST_ASSERT(setvar("kk000", 5, "bc", 2) == EC_SUCCESS);
- /* But this still won't fit */
- TEST_ASSERT(setvar("kk999", 5, "de", 2) == EC_ERROR_OVERFLOW);
-
- return EC_SUCCESS;
-}
-
-void run_test(void)
-{
- test_reset();
-
- RUN_TEST(check_init);
- RUN_TEST(simple_write);
- RUN_TEST(simple_search);
- RUN_TEST(simple_delete);
- RUN_TEST(complex_write);
- RUN_TEST(weird_keys);
- RUN_TEST(weird_values);
- RUN_TEST(fill_it_up);
-
- test_print_result();
-}
diff --git a/test/nvmem_vars.tasklist b/test/nvmem_vars.tasklist
deleted file mode 100644
index cc500f5e8f..0000000000
--- a/test/nvmem_vars.tasklist
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * List of enabled tasks in the priority order
- *
- * The first one has the lowest priority.
- *
- * For each task, use the macro TASK_TEST(n, r, d, s) where :
- * 'n' in the name of the task
- * 'r' in the main routine of the task
- * 'd' in an opaque parameter passed to the routine at startup
- * 's' is the stack size in bytes; must be a multiple of 8
- */
-#define CONFIG_TEST_TASK_LIST /* No test task */
diff --git a/test/pinweaver.c b/test/pinweaver.c
index 71f8f0387d..079fbe2b88 100644
--- a/test/pinweaver.c
+++ b/test/pinweaver.c
@@ -16,6 +16,8 @@
#include "test_util.h"
+#include <stdlib.h>
+
struct pw_test_data_t {
union {
struct pw_request_t request;
@@ -152,13 +154,10 @@ const uint8_t DEFAULT_PCR_DIGEST[] = {
/* Config Variables and defines for Mocks.
*/
-struct tuple MOCK_pw_tuple;
struct pw_long_term_storage_t MOCK_pw_long_term_storage;
struct pw_log_storage_t MOCK_pw_log_storage;
int MOCK_getvar_ret = EC_SUCCESS;
int MOCK_setvar_ret = EC_SUCCESS;
-int MOCK_writevars_ret = EC_SUCCESS;
-void *MOCK_tuple_val_ret;
const uint8_t *MOCK_rand_bytes_src;
size_t MOCK_rand_bytes_offset;
@@ -342,7 +341,6 @@ static void setup_storage(int num_operations)
{
MOCK_getvar_ret = EC_SUCCESS;
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
memset(&MOCK_pw_long_term_storage, 0,
sizeof(MOCK_pw_long_term_storage));
@@ -470,7 +468,6 @@ static void setup_reset_tree_defaults(struct merkle_tree_t *merkle_tree,
MOCK_rand_bytes_len = sizeof(EMPTY_TREE.key_derivation_nonce);
MOCK_appkey_derive_fail = EC_SUCCESS;
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_insert_leaf_defaults(struct merkle_tree_t *merkle_tree,
@@ -513,7 +510,6 @@ static void setup_insert_leaf_defaults(struct merkle_tree_t *merkle_tree,
MOCK_hmac = DEFAULT_HMAC;
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_remove_leaf_defaults(struct merkle_tree_t *merkle_tree,
@@ -540,7 +536,6 @@ static void setup_remove_leaf_defaults(struct merkle_tree_t *merkle_tree,
setup_default_empty_path(request->data.remove_leaf.path_hashes);
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_try_auth_defaults_with_leaf(
@@ -598,7 +593,6 @@ static void setup_try_auth_defaults_with_leaf(
MOCK_hash_update_cb = auth_hash_update_cb;
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_try_auth_defaults(struct merkle_tree_t *merkle_tree,
@@ -645,7 +639,6 @@ static void setup_reset_auth_defaults(struct merkle_tree_t *merkle_tree,
MOCK_hmac = EMPTY_HMAC; /* Gets overwritten by auth_hash_update_cb. */
MOCK_aes_fail = 0;
MOCK_setvar_ret = EC_SUCCESS;
- MOCK_writevars_ret = EC_SUCCESS;
}
static void setup_get_log_defaults(struct merkle_tree_t *merkle_tree,
@@ -800,35 +793,57 @@ uint8_t get_current_pcr_digest(const uint8_t bitmask[2],
/******************************************************************************/
/* Mock implementations of nvmem_vars functionality.
*/
-const struct tuple *getvar(const uint8_t *key, uint8_t key_len)
+struct tuple *getvar(const uint8_t *key, uint8_t key_len)
{
+ struct tuple *var = NULL;
+ size_t i;
+
+ const struct {
+ size_t key_len;
+ const void *key;
+ size_t val_size;
+ const void *val;
+ } vars[] = {
+ {sizeof(PW_TREE_VAR) - 1, PW_TREE_VAR,
+ sizeof(MOCK_pw_long_term_storage), &MOCK_pw_long_term_storage},
+ {sizeof(PW_LOG_VAR0) - 1, PW_LOG_VAR0,
+ sizeof(MOCK_pw_log_storage), &MOCK_pw_log_storage},
+ };
+
+ if (!key || !key_len)
+ return NULL;
+
if (MOCK_getvar_ret != EC_SUCCESS)
return NULL;
- MOCK_pw_tuple.flags = 0;
- MOCK_pw_tuple.key_len = key_len;
+ for (i = 0; i < ARRAY_SIZE(vars); i++) {
+ if ((key_len != vars[i].key_len) ||
+ memcmp(key, vars[i].key, key_len)) {
+ continue;
+ }
+ var = malloc(sizeof(struct tuple) + key_len + vars[i].val_size);
+ var->flags = 0;
+ var->val_len = vars[i].val_size;
+ memcpy(var->data_ + var->key_len, vars[i].val, var->val_len);
+ break;
+ }
- if (key_len == (sizeof(PW_TREE_VAR) - 1) &&
- memcmp(key, PW_TREE_VAR, (sizeof(PW_TREE_VAR) - 1)) == 0) {
- MOCK_pw_tuple.val_len = sizeof(MOCK_pw_long_term_storage);
- MOCK_tuple_val_ret = &MOCK_pw_long_term_storage;
- return &MOCK_pw_tuple;
- } else if (key_len == (sizeof(PW_LOG_VAR0) - 1) &&
- memcmp(key, PW_LOG_VAR0, (sizeof(PW_LOG_VAR0) - 1)) == 0) {
- MOCK_pw_tuple.val_len = sizeof(struct pw_log_storage_t);
- MOCK_tuple_val_ret = &MOCK_pw_log_storage;
- return &MOCK_pw_tuple;
- } else
- return NULL;
+ return var;
}
+int freevar(struct tuple *var)
+{
+ free(var);
+
+ return EC_SUCCESS;
+}
const uint8_t *tuple_val(const struct tuple *tpl)
{
- return MOCK_tuple_val_ret;
+ return tpl->data_ + tpl->key_len;
}
-int setvar(const uint8_t *key, uint8_t key_len,
- const uint8_t *val, uint8_t val_len)
+int setvar(const uint8_t *key, uint8_t key_len, const uint8_t *val,
+ uint8_t val_len)
{
if (MOCK_setvar_ret != EC_SUCCESS)
return MOCK_setvar_ret;
@@ -847,11 +862,6 @@ int setvar(const uint8_t *key, uint8_t key_len,
return EC_ERROR_UNKNOWN;
}
-int writevars(void)
-{
- return MOCK_writevars_ret;
-}
-
/******************************************************************************/
/* Mock implementations of TRNG functionality.
*/
@@ -1214,7 +1224,7 @@ static int handle_reset_tree_nv_fail(void)
setup_reset_tree_defaults(&merkle_tree, &buf.request);
- MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
+ MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@@ -1364,7 +1374,7 @@ static int handle_insert_leaf_nv_fail(void)
setup_insert_leaf_defaults(&merkle_tree, &buf.request);
- MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
+ MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@@ -1535,7 +1545,7 @@ static int handle_remove_leaf_nv_fail(void)
setup_remove_leaf_defaults(&merkle_tree, &buf.request);
- MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
+ MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@@ -1789,7 +1799,7 @@ static int handle_try_auth_nv_fail(void)
force_restart_count(0);
force_time((timestamp_t){.val = 65 * SECOND});
- MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
+ MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
@@ -2136,7 +2146,7 @@ static int handle_reset_auth_nv_fail(void)
setup_reset_auth_defaults(&merkle_tree, &buf.request);
- MOCK_writevars_ret = PW_ERR_NV_LENGTH_MISMATCH;
+ MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
PW_ERR_NV_LENGTH_MISMATCH);
diff --git a/test/test_config.h b/test/test_config.h
index 22f497bcc0..17e7d6f44d 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -257,53 +257,37 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_USB_PD_PORT_COUNT 2
#endif
-#ifdef TEST_NVMEM
+#if defined(TEST_NVMEM) || defined(TEST_NVMEM_VARS)
+#define CONFIG_CRC8
+#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
+#define CONFIG_FLASH_LOG
+#define CONFIG_FLASH_LOG_BASE CONFIG_PROGRAM_MEMORY_BASE
+#define CONFIG_FLASH_LOG_SPACE 0x800
#define CONFIG_FLASH_NVMEM
-#define CONFIG_FLASH_NVMEM_OFFSET_A 0x1000
-#define CONFIG_FLASH_NVMEM_OFFSET_B 0x4000
-#define CONFIG_FLASH_NVMEM_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \
- CONFIG_FLASH_NVMEM_OFFSET_A)
-#define CONFIG_FLASH_NVMEM_BASE_B (CONFIG_PROGRAM_MEMORY_BASE + \
- CONFIG_FLASH_NVMEM_OFFSET_B)
-#define CONFIG_FLASH_NVMEM_SIZE 0x4000
+#define CONFIG_FLASH_NVMEM_OFFSET_A 0x3d000
+#define CONFIG_FLASH_NVMEM_OFFSET_B 0x7d000
+#define CONFIG_FLASH_NVMEM_BASE_A \
+ (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_A)
+#define CONFIG_FLASH_NVMEM_BASE_B \
+ (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_B)
+#define CONFIG_FLASH_NEW_NVMEM_BASE_A (CONFIG_FLASH_NVMEM_BASE_A + 0x800)
+#define CONFIG_FLASH_NEW_NVMEM_BASE_B (CONFIG_FLASH_NVMEM_BASE_B + 0x800)
+#define CONFIG_MALLOC
+/* This is legacy NVMEM partition size. */
+#define NVMEM_PARTITION_SIZE 0x3000
+#define NEW_FLASH_HALF_NVMEM_SIZE \
+ (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
+#define NEW_NVMEM_PARTITION_SIZE (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
+#define NEW_NVMEM_TOTAL_PAGES \
+ (2 * NEW_NVMEM_PARTITION_SIZE / CONFIG_FLASH_BANK_SIZE)
#define CONFIG_SW_CRC
-
-#define NVMEM_PARTITION_SIZE \
- (CONFIG_FLASH_NVMEM_SIZE / NVMEM_NUM_PARTITIONS)
-/* User buffer definitions for test purposes */
-#define NVMEM_USER_2_SIZE 0x201
-#define NVMEM_USER_1_SIZE 0x402
-#define NVMEM_USER_0_SIZE (NVMEM_PARTITION_SIZE - \
- NVMEM_USER_2_SIZE - NVMEM_USER_1_SIZE - \
- sizeof(struct nvmem_tag))
+#define CONFIG_FLASH_NVMEM_VARS
#ifndef __ASSEMBLER__
-enum nvmem_users {
- NVMEM_USER_0,
- NVMEM_USER_1,
- NVMEM_USER_2,
- NVMEM_NUM_USERS
-};
+enum nvmem_users { NVMEM_TPM = 0, NVMEM_CR50, NVMEM_NUM_USERS };
#endif
#endif
-#ifdef TEST_NVMEM_VARS
-#define NVMEM_PARTITION_SIZE 0x3000
-#define CONFIG_FLASH_NVMEM_VARS
-#ifndef __ASSEMBLER__
-/* Define the user region numbers */
-enum nvmem_users {
- CONFIG_FLASH_NVMEM_VARS_USER_NUM,
- NVMEM_NUM_USERS
-};
-/* Define a test var. */
-enum nvmem_vars {
- NVMEM_VAR_TEST_VAR,
-};
-#endif
-#define CONFIG_FLASH_NVMEM_VARS_USER_SIZE 600
-#endif /* TEST_NVMEM_VARS */
-
#ifdef TEST_PINWEAVER
#define CONFIG_DCRYPTO_MOCK
#define CONFIG_PINWEAVER